⑴ linux下如何實現shell多線程編程以提高應用程序的響應
Linux中多線程編程擁有提高應用程序的響應、使多cpu系統更加有效等優點,下面小編將通過Linux下shell多線程編程的例子給大家講解下多線程編程的過程,一起來了解下吧。
#!/bin/bash
#———————————————————————————–
# 此例子說明了一種用wait、read命令模擬多線程的一種技巧
# 此技巧往往用於多主機檢查,比如ssh登錄、ping等等這種單進程比較慢而不耗費cpu的情況
# 還說明了多線程的控制
#———————————————————————————–
function a_sub
{
# 此處定義一個函數,作為一個線程(子進程)
sleep 3 # 線程的作用是sleep 3s
}
tmp_fifofile=「/tmp/$.fifo」 mkfifo $tmp_fifofile # 新建一個fifo類型的文件
exec 6《》$tmp_fifofile # 將fd6指向fifo類型
rm $tmp_fifofile thread=15 # 此處定義線程數
for
((i=0;i《$thread;i++));do echo
done 》&6 # 事實上就是在fd6中放置了$thread個回車符
for
((i=0;i《50;i++));do # 50次循環,可以理解為50個主機,或其他
read -u6 # 一個read -u6命令執行一次,就從fd6中減去一個回車符,然後向下執行,
# fd6中沒有回車符的時候,就停在這了,從而實現了線程數量控制
{ # 此處子進程開始執行,被放到後台
a_sub &&
{ # 此處可以用來判斷子進程的邏輯
echo 「a_sub is finished」
}
||
{ echo 「sub error」
}
echo 》&6 # 當進程結束以後,再向fd6中加上一個回車符,即補上了read -u6減去的那個
}
& done wait # 等待所有的後檯子進程結束
exec 6》&- # 關閉df6 exit 0
說明:
此程序中的命令
mkfifo tmpfile
和linux中的命令
mknod tmpfile p
效?果相同。區別是mkfifo為POSIX標准,因此推薦使用它。該命令創建了一個先入先出的管道文件,並為其分配文件標志符6。管道文件是進程之間通信的一種方式,注意這一句很重要
exec 6《》$tmp_fifofile # 將fd6指向fifo類型
如果沒有這句,在向文件$tmp_fifofile或者&6寫入數據時,程序會被阻塞,直到有read讀出了管道文件中的數據為止。而執行了上面這一句後就可以在程序運行期間不斷向fifo類型的文件寫入數據而不會阻塞,並且數據會被保存下來以供read程序讀出。
通過運行命令:
time 。/multithread.sh 》/dev/null
最終運算時間: 50/15 = 3組(每組15)+1組(5個《15 組成一個組)= 4組,每組花費時間:3秒,
則 3 * 4 = 12 秒。
傳統非多線程的代碼 運算時間: 50 * 3 = 150 秒。
上面就是Linux下shell多線程編程的實例介紹了,使用多線程編程還能夠改善程序結構,有興趣的朋友不妨試試看吧。
⑵ Linux信號量機制實現讀者寫者問題
生產者/消費者問題在windows2000下的實現
一、問題描述
生產者-消費者問題是一個經典的進程同步問題,該問題最早由Dijkstra提出,用以演示他提出的信號量機制。本作業要求設計在同一個進程地址空間內執行的兩個線程。生產者線程生產物品,然後將物品放置在一個空緩沖區中供消費者線程消費。消費者線程從緩沖區中獲得物品,然後釋放緩沖區。當生產者線程生產物品時,如果沒有空緩沖區可用,那麼生產者線程必須等待消費者線程釋放出一個空緩沖區。當消費者線程消費物品時,如果沒有滿的緩沖區,那麼消費者線程將被阻塞,直到新的物品被生產出來。
二、實現代碼
#include <windows.h>
#include <iostream>
const unsigned short SIZE_OF_BUFFER = 10; //緩沖區長度
unsigned short ProctID = 0; //產品號
unsigned short ConsumeID = 0; //將被消耗的產品號
unsigned short in = 0; //產品進緩沖區時的緩沖區下標
unsigned short out = 0; //產品出緩沖區時的緩沖區下標
int g_buffer[SIZE_OF_BUFFER]; //緩沖區是個循環隊列
bool g_continue = true; //控製程序結束
HANDLE g_hMutex; //用於線程間的互斥
HANDLE g_hFullSemaphore; //當緩沖區滿時迫使生產者等待
HANDLE g_hEmptySemaphore; //當緩沖區空時迫使消費者等待
DWORD WINAPI Procer(LPVOID); //生產者線程
DWORD WINAPI Consumer(LPVOID); //消費者線程
int main()
{
//創建各個互斥信號
g_hMutex = CreateMutex(NULL,FALSE,NULL);
g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);
//調整下面的數值,可以發現,當生產者個數多於消費者個數時,
//生產速度快,生產者經常等待消費者;反之,消費者經常等待
const unsigned short PRODUCERS_COUNT = 3; //生產者的個數
const unsigned short CONSUMERS_COUNT = 1; //消費者的個數
//總的線程數
const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;
DWORD procerID[CONSUMERS_COUNT]; //生產者線程的標識符
DWORD consumerID[THREADS_COUNT]; //消費者線程的標識符
//創建生產者線程
for (int i=0;i<PRODUCERS_COUNT;++i){
hThreads[i]=CreateThread(NULL,0,Procer,NULL,0,&procerID[i]);
if (hThreads[i]==NULL) return -1;
}
//創建消費者線程
for (int i=0;i<CONSUMERS_COUNT;++i){
hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
if (hThreads[i]==NULL) return -1;
}
while(g_continue){
if(getchar()){ //按回車後終止程序運行
g_continue = false;
}
}
return 0;
}
//生產一個產品。簡單模擬了一下,僅輸出新產品的ID號
void Proce()
{
std::cerr << "Procing " << ++ProctID << " ... ";
std::cerr << "Succeed" << std::endl;
}
//把新生產的產品放入緩沖區
void Append()
{
std::cerr << "Appending a proct ... ";
g_buffer[in] = ProctID;
in = (in+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;
//輸出緩沖區當前的狀態
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生產";
if (i==out) std::cout << " <-- 消費";
std::cout << std::endl;
}
}
//從緩沖區中取出一個產品
void Take()
{
std::cerr << "Taking a proct ... ";
ConsumeID = g_buffer[out];
out = (out+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;
//輸出緩沖區當前的狀態
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生產";
if (i==out) std::cout << " <-- 消費";
std::cout << std::endl;
}
}
//消耗一個產品
void Consume()
{
std::cerr << "Consuming " << ConsumeID << " ... ";
std::cerr << "Succeed" << std::endl;
}
//生產者
DWORD WINAPI Procer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hFullSemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Proce();
Append();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hEmptySemaphore,1,NULL);
}
return 0;
}
//消費者
DWORD WINAPI Consumer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hEmptySemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Take();
Consume();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hFullSemaphore,1,NULL);
}
return 0;
}
⑶ Linux 多線程編程(二)2019-08-10
三種專門用於線程同步的機制:POSIX信號量,互斥量和條件變數.
在Linux上信號量API有兩組,一組是System V IPC信號量,即PV操作,另外就是POSIX信號量,POSIX信號量的名字都是以sem_開頭.
phshared參數指定信號量的類型,若其值為0,就表示這個信號量是當前進程的局部信號量,否則該信號量可以在多個進程之間共享.value值指定信號量的初始值,一般與下面的sem_wait函數相對應.
其中比較重要的函數sem_wait函數會以原子操作的方式將信號量的值減一,如果信號量的值為零,則sem_wait將會阻塞,信號量的值可以在sem_init函數中的value初始化;sem_trywait函數是sem_wait的非阻塞版本;sem_post函數將以原子的操作對信號量加一,當信號量的值大於0時,其他正在調用sem_wait等待信號量的線程將被喚醒.
這些函數成功時返回0,失敗則返回-1並設置errno.
生產者消費者模型:
生產者對應一個信號量:sem_t procer;
消費者對應一個信號量:sem_t customer;
sem_init(&procer,2)----生產者擁有資源,可以工作;
sem_init(&customer,0)----消費者沒有資源,阻塞;
在訪問公共資源前對互斥量設置(加鎖),確保同一時間只有一個線程訪問數據,在訪問完成後再釋放(解鎖)互斥量.
互斥鎖的運行方式:串列訪問共享資源;
信號量的運行方式:並行訪問共享資源;
互斥量用pthread_mutex_t數據類型表示,在使用互斥量之前,必須使用pthread_mutex_init函數對它進行初始化,注意,使用完畢後需調用pthread_mutex_destroy.
pthread_mutex_init用於初始化互斥鎖,mutexattr用於指定互斥鎖的屬性,若為NULL,則表示默認屬性。除了用這個函數初始化互斥所外,還可以用如下方式初始化:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER。
pthread_mutex_destroy用於銷毀互斥鎖,以釋放佔用的內核資源,銷毀一個已經加鎖的互斥鎖將導致不可預期的後果。
pthread_mutex_lock以原子操作給一個互斥鎖加鎖。如果目標互斥鎖已經被加鎖,則pthread_mutex_lock則被阻塞,直到該互斥鎖佔有者把它給解鎖.
pthread_mutex_trylock和pthread_mutex_lock類似,不過它始終立即返回,而不論被操作的互斥鎖是否加鎖,是pthread_mutex_lock的非阻塞版本.當目標互斥鎖未被加鎖時,pthread_mutex_trylock進行加鎖操作;否則將返回EBUSY錯誤碼。注意:這里討論的pthread_mutex_lock和pthread_mutex_trylock是針對普通鎖而言的,對於其他類型的鎖,這兩個加鎖函數會有不同的行為.
pthread_mutex_unlock以原子操作方式給一個互斥鎖進行解鎖操作。如果此時有其他線程正在等待這個互斥鎖,則這些線程中的一個將獲得它.
三個列印機輪流列印:
輸出結果:
如果說互斥鎖是用於同步線程對共享數據的訪問的話,那麼條件變數就是用於在線程之間同步共享數據的值.條件變數提供了一種線程之間通信的機制:當某個共享數據達到某個值時,喚醒等待這個共享數據的線程.
條件變數會在條件不滿足的情況下阻塞線程.且條件變數和互斥量一起使用,允許線程以無競爭的方式等待特定的條件發生.
其中pthread_cond_broadcast函數以廣播的形式喚醒所有等待目標條件變數的線程,pthread_cond_signal函數用於喚醒一個等待目標條件變數線程.但有時候我們可能需要喚醒一個固定的線程,可以通過間接的方法實現:定義一個能夠唯一標識目標線程的全局變數,在喚醒等待條件變數的線程前先設置該變數為目標線程,然後採用廣播的方式喚醒所有等待的線程,這些線程被喚醒之後都檢查該變數以判斷是否是自己.
採用條件變數+互斥鎖實現生產者消費者模型:
運行結果:
阻塞隊列+生產者消費者
運行結果:
⑷ linux單進程如何實現多核cpu多線程分配
linux下的單進程多線程的程序,要實現每個線程平均分配到多核cpu,主要有2個方法
1:利用linux系統自己的線程切換機制,有一個服務叫做irqbalance,這個服務是linux系統自帶的,默認會啟動,這個服務的作用就是把多線程平均分配到CPU的每個核上面,只要這個服務不停止,多線程分配就可以自己實現。但是要注意,如果線程函數內部的有某個循環,且該循環內沒有任何系統調用的話,可能會導致這個線程的CPU時間無法被切換出去。也就是占滿CPU現象,此時加個系統調用,例如sleep,線程所佔的CPU時間就可以切換出去了。
2:利用pthread庫自帶的線程親和性設置函數,來設置線程在某個CPU核心上跑,這個需要在程序內部實現。同時注意不要和進程親和性設置搞混淆了
intpthread_setaffinity_np(pthread_tthread,size_tcpusetsize,
constcpu_set_t*cpuset);
intpthread_getaffinity_np(pthread_tthread,size_tcpusetsize,
cpu_set_t*cpuset);
從函數名以及參數名都很明了,唯一需要點解釋下的可能就是cpu_set_t這個結構體了。這個結構體的理解類似於select中的fd_set,可以理解為cpu集,也是通過約定好的宏來進行清除、設置以及判斷:
//初始化,設為空
voidCPU_ZERO(cpu_set_t*set);
//將某個cpu加入cpu集中
voidCPU_SET(intcpu,cpu_set_t*set);
//將某個cpu從cpu集中移出
voidCPU_CLR(intcpu,cpu_set_t*set);
//判斷某個cpu是否已在cpu集中設置了
intCPU_ISSET(intcpu,constcpu_set_t*set);
⑸ Linux多進程和線程同步的幾種方式
Linux 線程同步的三種方法
線程的最大特點是資源的共享性,但資源共享中的同步問題是多線程編程的難點。linux下提供了多種方式來處理線程同步,最常用的是互斥鎖、條件變數和信號量。
一、互斥鎖(mutex)
通過鎖機制實現線程間的同步。
初始化鎖。在Linux下,線程的互斥量數據類型是pthread_mutex_t。在使用前,要對它進行初始化。
靜態分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
動態分配:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);
加鎖。對共享資源的訪問,要對互斥量進行加鎖,如果互斥量已經上了鎖,調用線程會阻塞,直到互斥量被解鎖。
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
解鎖。在完成了對共享資源的訪問後,要對互斥量進行解鎖。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
銷毀鎖。鎖在是使用完成後,需要進行銷毀以釋放資源。
int pthread_mutex_destroy(pthread_mutex *mutex);
[csharp] view plain
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include "iostream"
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int tmp;
void* thread(void *arg)
{
cout << "thread id is " << pthread_self() << endl;
pthread_mutex_lock(&mutex);
tmp = 12;
cout << "Now a is " << tmp << endl;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t id;
cout << "main thread id is " << pthread_self() << endl;
tmp = 3;
cout << "In main func tmp = " << tmp << endl;
if (!pthread_create(&id, NULL, thread, NULL))
{
cout << "Create thread success!" << endl;
}
else
{
cout << "Create thread failed!" << endl;
}
pthread_join(id, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
//編譯:g++ -o thread testthread.cpp -lpthread
二、條件變數(cond)
互斥鎖不同,條件變數是用來等待而不是用來上鎖的。條件變數用來自動阻塞一個線程,直到某特殊情況發生為止。通常條件變數和互斥鎖同時使用。條件變數分為兩部分: 條件和變數。條件本身是由互斥量保護的。線程在改變條件狀態前先要鎖住互斥量。條件變數使我們可以睡眠等待某種條件出現。條件變數是利用線程間共享的全局變數進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變數的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立信號)。條件的檢測是在互斥鎖的保護下進行的。如果一個條件為假,一個線程自動阻塞,並釋放等待狀態改變的互斥鎖。如果另一個線程改變了條件,它發信號給關聯的條件變數,喚醒一個或多個等待它的線程,重新獲得互斥鎖,重新評價條件。如果兩進程共享可讀寫的內存,條件變數可以被用來實現這兩進程間的線程同步。
初始化條件變數。
靜態態初始化,pthread_cond_t cond = PTHREAD_COND_INITIALIER;
動態初始化,int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
等待條件成立。釋放鎖,同時阻塞等待條件變數為真才行。timewait()設置等待時間,仍未signal,返回ETIMEOUT(加鎖保證只有一個線程wait)
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
激活條件變數。pthread_cond_signal,pthread_cond_broadcast(激活所有等待線程)
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有線程的阻塞
清除條件變數。無線程等待,否則返回EBUSY
int pthread_cond_destroy(pthread_cond_t *cond);
[cpp] view plain
#include <stdio.h>
#include <pthread.h>
#include "stdlib.h"
#include "unistd.h"
pthread_mutex_t mutex;
pthread_cond_t cond;
void hander(void *arg)
{
free(arg);
(void)pthread_mutex_unlock(&mutex);
}
void *thread1(void *arg)
{
pthread_cleanup_push(hander, &mutex);
while(1)
{
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while(1)
{
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1,thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&thid1, NULL, thread1, NULL);
pthread_create(&thid2, NULL, thread2, NULL);
sleep(1);
do
{
pthread_cond_signal(&cond);
}while(1);
sleep(20);
pthread_exit(0);
return 0;
}
[cpp] view plain
#include <pthread.h>
#include <unistd.h>
#include "stdio.h"
#include "stdlib.h"
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct node
{
int n_number;
struct node *n_next;
}*head = NULL;
static void cleanup_handler(void *arg)
{
printf("Cleanup handler of second thread./n");
free(arg);
(void)pthread_mutex_unlock(&mtx);
}
static void *thread_func(void *arg)
{
struct node *p = NULL;
pthread_cleanup_push(cleanup_handler, p);
while (1)
{
//這個mutex主要是用來保證pthread_cond_wait的並發性
pthread_mutex_lock(&mtx);
while (head == NULL)
{
//這個while要特別說明一下,單個pthread_cond_wait功能很完善,為何
//這里要有一個while (head == NULL)呢?因為pthread_cond_wait里的線
//程可能會被意外喚醒,如果這個時候head != NULL,則不是我們想要的情況。
//這個時候,應該讓線程繼續進入pthread_cond_wait
// pthread_cond_wait會先解除之前的pthread_mutex_lock鎖定的mtx,
//然後阻塞在等待對列里休眠,直到再次被喚醒(大多數情況下是等待的條件成立
//而被喚醒,喚醒後,該進程會先鎖定先pthread_mutex_lock(&mtx);,再讀取資源
//用這個流程是比較清楚的
pthread_cond_wait(&cond, &mtx);
p = head;
head = head->n_next;
printf("Got %d from front of queue/n", p->n_number);
free(p);
}
pthread_mutex_unlock(&mtx); //臨界區數據操作完畢,釋放互斥鎖
}
pthread_cleanup_pop(0);
return 0;
}
int main(void)
{
pthread_t tid;
int i;
struct node *p;
//子線程會一直等待資源,類似生產者和消費者,但是這里的消費者可以是多個消費者,而
//不僅僅支持普通的單個消費者,這個模型雖然簡單,但是很強大
pthread_create(&tid, NULL, thread_func, NULL);
sleep(1);
for (i = 0; i < 10; i++)
{
p = (struct node*)malloc(sizeof(struct node));
p->n_number = i;
pthread_mutex_lock(&mtx); //需要操作head這個臨界資源,先加鎖,
p->n_next = head;
head = p;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx); //解鎖
sleep(1);
}
printf("thread 1 wanna end the line.So cancel thread 2./n");
//關於pthread_cancel,有一點額外的說明,它是從外部終止子線程,子線程會在最近的取消點,退出
//線程,而在我們的代碼里,最近的取消點肯定就是pthread_cond_wait()了。
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("All done -- exiting/n");
return 0;
}
三、信號量(sem)
如同進程一樣,線程也可以通過信號量來實現通信,雖然是輕量級的。信號量函數的名字都以"sem_"打頭。線程使用的基本信號量函數有四個。
信號量初始化。
int sem_init (sem_t *sem , int pshared, unsigned int value);
這是對由sem指定的信號量進行初始化,設置好它的共享選項(linux 只支持為0,即表示它是當前進程的局部信號量),然後給它一個初始值VALUE。
等待信號量。給信號量減1,然後等待直到信號量的值大於0。
int sem_wait(sem_t *sem);
釋放信號量。信號量值加1。並通知其他等待線程。
int sem_post(sem_t *sem);
銷毀信號量。我們用完信號量後都它進行清理。歸還佔有的一切資源。
int sem_destroy(sem_t *sem);
[cpp] view plain
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!/n", __func__);return;}
typedef struct _PrivInfo
{
sem_t s1;
sem_t s2;
time_t end_time;
}PrivInfo;
static void info_init (PrivInfo* thiz);
static void info_destroy (PrivInfo* thiz);
static void* pthread_func_1 (PrivInfo* thiz);
static void* pthread_func_2 (PrivInfo* thiz);
int main (int argc, char** argv)
{
pthread_t pt_1 = 0;
pthread_t pt_2 = 0;
int ret = 0;
PrivInfo* thiz = NULL;
thiz = (PrivInfo* )malloc (sizeof (PrivInfo));
if (thiz == NULL)
{
printf ("[%s]: Failed to malloc priv./n");
return -1;
}
info_init (thiz);
ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);
if (ret != 0)
{
perror ("pthread_1_create:");
}
ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);
if (ret != 0)
{
perror ("pthread_2_create:");
}
pthread_join (pt_1, NULL);
pthread_join (pt_2, NULL);
info_destroy (thiz);
return 0;
}
static void info_init (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
thiz->end_time = time(NULL) + 10;
sem_init (&thiz->s1, 0, 1);
sem_init (&thiz->s2, 0, 0);
return;
}
static void info_destroy (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
sem_destroy (&thiz->s1);
sem_destroy (&thiz->s2);
free (thiz);
thiz = NULL;
return;
}
static void* pthread_func_1 (PrivInfo* thiz)
{
return_if_fail(thiz != NULL);
while (time(NULL) < thiz->end_time)
{
sem_wait (&thiz->s2);
printf ("pthread1: pthread1 get the lock./n");
sem_post (&thiz->s1);
printf ("pthread1: pthread1 unlock/n");
sleep (1);
}
return;
}
static void* pthread_func_2 (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
while (time (NULL) < thiz->end_time)
{
sem_wait (&thiz->s1);
printf ("pthread2: pthread2 get the unlock./n");
sem_post (&thiz->s2);
printf ("pthread2: pthread2 unlock./n");
sleep (1);
}
return;
}
⑹ 在linux下用c語言實現用多進程同步方法演示「生產者-消費者」問題
這個問題需要的知識主要包括:
1 多進程間進行通信;
2 使用同步信號量(semaphore)和互斥信號量(mutex)進行數據保護。
參考代碼如下,可以參照注釋輔助理解:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#defineN2//消費者或者生產者的數目
#defineM10//緩沖數目
intin=0;//生產者放置產品的位置
intout=0;//消費者取產品的位置
intbuff[M]={0};//緩沖初始化為0,開始時沒有產品
sem_tempty_sem;//同步信號量,當滿了時阻止生產者放產品
sem_tfull_sem;//同步信號量,當沒產品時阻止消費者消費
pthread_mutex_tmutex;//互斥信號量,一次只有一個線程訪問緩沖
intproct_id=0;//生產者id
intprochase_id=0;//消費者id
/*列印緩沖情況*/
voidprint()
{
inti;
for(i=0;i<M;i++)
printf("%d",buff[i]);
printf(" ");
}
/*生產者方法*/
void*proct()
{
intid=++proct_id;
while(1)
{
//用sleep的數量可以調節生產和消費的速度,便於觀察
sleep(1);
//sleep(1);
sem_wait(&empty_sem);
pthread_mutex_lock(&mutex);
in=in%M;
printf("proct%din%d.like: ",id,in);
buff[in]=1;
print();
++in;
pthread_mutex_unlock(&mutex);
sem_post(&full_sem);
}
}
/*消費者方法*/
void*prochase()
{
intid=++prochase_id;
while(1)
{
//用sleep的數量可以調節生產和消費的速度,便於觀察
sleep(1);
//sleep(1);
sem_wait(&full_sem);
pthread_mutex_lock(&mutex);
out=out%M;
printf("prochase%din%d.like: ",id,out);
buff[out]=0;
print();
++out;
pthread_mutex_unlock(&mutex);
sem_post(&empty_sem);
}
}
intmain()
{
pthread_tid1[N];
pthread_tid2[N];
inti;
intret[N];
//初始化同步信號量
intini1=sem_init(&empty_sem,0,M);
intini2=sem_init(&full_sem,0,0);
if(ini1&&ini2!=0)
{
printf("seminitfailed ");
exit(1);
}
//初始化互斥信號量
intini3=pthread_mutex_init(&mutex,NULL);
if(ini3!=0)
{
printf("mutexinitfailed ");
exit(1);
}
//創建N個生產者線程
for(i=0;i<N;i++)
{
ret[i]=pthread_create(&id1[i],NULL,proct,(void*)(&i));
if(ret[i]!=0)
{
printf("proct%dcreationfailed ",i);
exit(1);
}
}
//創建N個消費者線程
for(i=0;i<N;i++)
{
ret[i]=pthread_create(&id2[i],NULL,prochase,NULL);
if(ret[i]!=0)
{
printf("prochase%dcreationfailed ",i);
exit(1);
}
}
//銷毀線程
for(i=0;i<N;i++)
{
pthread_join(id1[i],NULL);
pthread_join(id2[i],NULL);
}
exit(0);
}
在Linux下編譯的時候,要在編譯命令中加入選項-lpthread以包含多線程支持。比如存儲的C文件為demo.c,要生成的可執行文件為demo。可以使用命令:
gcc demo.c -o demo -lpthread
程序中為便於觀察,使用了sleep(1);來暫停運行,所以查看輸出的時候可以看到,輸出是每秒列印一次的。
⑺ 請問linux下C編程多線程同步和非同步的區別,如何能實現程序的同步和非同步編程
同步和非同步抄的區別:
1、同步就是說多個任務之間是有先後關系的,一個任務需要等待另一個任務執行完畢才能繼續執行。
2、非同步就是說多個任務之間沒有先後關系,不需要相互等待各做各的事。
同步編程方法:
1、信號量
2、互斥量
非同步無需考慮資源沖突,不需特別處理。