c語言pthreadcondt,c語言pthread_join

本文目錄一覽:

在linux下用c語言實現用多進程同步方法演示“生產者-消費者”問題

這個問題需要的知識主要包括:

1 多進程間進行通信;

2 使用同步信號量(semaphore)和互斥信號量(mutex)進行數據保護。

參考代碼如下,可以參照注釋輔助理解:

#include stdio.h

#include stdlib.h

#include unistd.h

#include pthread.h

#include semaphore.h

#define N 2   // 消費者或者生產者的數目

#define M 10 // 緩衝數目

int in = 0;   // 生產者放置產品的位置

int out = 0; // 消費者取產品的位置

int buff[M] = {0}; // 緩衝初始化為0, 開始時沒有產品

sem_t empty_sem; // 同步信號量, 當滿了時阻止生產者放產品

sem_t full_sem;   // 同步信號量, 當沒產品時阻止消費者消費

pthread_mutex_t mutex; // 互斥信號量, 一次只有一個線程訪問緩衝

int product_id = 0;   //生產者id

int prochase_id = 0; //消費者id

/* 打印緩衝情況 */

void print()

{

int i;

for(i = 0; i  M; i++)

   printf(“%d “, buff[i]);

printf(“\n”);

}

/* 生產者方法 */ 

void *product()

{

int id = ++product_id;

while(1)

{

   // 用sleep的數量可以調節生產和消費的速度,便於觀察

   sleep(1);

   //sleep(1);

  

   sem_wait(empty_sem);

   pthread_mutex_lock(mutex);

  

   in = in % M;

   printf(“product%d in %d. like: \t”, id, in);

  

   buff[in] = 1;  

   print();  

   ++in;

  

   pthread_mutex_unlock(mutex);

   sem_post(full_sem);  

}

}

/* 消費者方法 */

void *prochase()

{

int id = ++prochase_id;

while(1)

{

   // 用sleep的數量可以調節生產和消費的速度,便於觀察

   sleep(1);

//sleep(1);

  

   sem_wait(full_sem);

   pthread_mutex_lock(mutex);

  

   out = out % M;

   printf(“prochase%d in %d. like: \t”, id, out);

  

   buff[out] = 0;

   print();

   ++out;

  

   pthread_mutex_unlock(mutex);

   sem_post(empty_sem);

}

}

int main()

{

pthread_t id1[N];

pthread_t id2[N];

int i;

int ret[N];

// 初始化同步信號量

int ini1 = sem_init(empty_sem, 0, M); 

int ini2 = sem_init(full_sem, 0, 0);  

if(ini1  ini2 != 0)

{

   printf(“sem init failed \n”);

   exit(1);

//初始化互斥信號量 

int ini3 = pthread_mutex_init(mutex, NULL);

if(ini3 != 0)

{

   printf(“mutex init failed \n”);

   exit(1);

// 創建N個生產者線程

for(i = 0; i  N; i++)

{

   ret[i] = pthread_create(id1[i], NULL, product, (void *)(i));

   if(ret[i] != 0)

   {

    printf(“product%d creation failed \n”, 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%d creation failed \n”, 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);來暫停運行,所以查看輸出的時候可以看到,輸出是每秒打印一次的。

如何使用pthread

怎樣知道一個pthread

如果需要只終止某個線程而不終止整個進程,可以有三種方法:

1.從線程函數return。這種方法對主線程不適用,從main函數return相當於調用exit。

2.一個線程可以調用pthread_cancel終止同一進程中的另一個線程。

3.線程可以調用pthread_exit終止自己。

使用條件變量進行線程間的同步

先看一下APUE第三版對於條件變量的說明:

條件變量是另一種線程同步機制,它為線程間共享的對象提供了同步的方法。當條件變量配合互斥鎖(Mutex)使用時,允許多個線程處在一種自由等待任意條件發生的狀態。

條件變量自身由互斥鎖(Mutex)保護。線程必須在修改條件狀態之前先對其上鎖,其他線程不會在獲取鎖之前被通知到其狀態變化,因為只有獲取到鎖才可以計算條件。

條件變量的數據類型是 pthread_cond_t ,條件變量屬性的類型是 pthread_condattr_t ,它們都包含在頭文件pthread.h中。

條件變量使用之前必須初始化,有兩種方法:

需要釋放條件變量時,使用pthread_cond_destroy即可。

調用phread_cond_wait或pthread_cond_timewait(以下簡稱wait函數)可以使當前線程等待某一條件的發生。兩者的區別在於後者可以指定等待時間。

調用wait函數時,系統使調用線程進入等待狀態後 釋放鎖 (所以我們必須先加鎖後調用wait函數)。在這一步操作中的檢查條件和進入等待是 原子操作 ,所以線程不會錯過條件的變化。當wait函數返回時,mutex會 再次被加鎖 。

其中pthread_cond_timewait中用到的timespec結構定義如下:

需要注意的是,timespec是一個絕對時間,所以在使用前我們需要先取得當前時間,再加上等待時間。例如下面這樣:

如果時間到了還沒有等到條件變化,函數會對mutex重新加鎖並返回一個ETIMEOUT的錯誤。

當wait函數返回成功時, 需要重新檢查條件 ,因為條件有可能已經被其他線程修改。

當條件滿足時,可以用這兩個函數用來通知其他線程。

pthread_cond_signal會喚醒至少一個等待的線程,而pthread_cond_broadcast會喚醒所有等待的線程。必須注意的是:我們 必須在狀態發生變化之後再發送信號給其他線程 。

條件變量的數據類型是 pthread_cond_t ,它主要有兩種屬性:

設置進程間共享屬性:

設置時鐘屬性:

pthread_cond_timewait函數用於在等待條件變量時提供超時功能,不過該函數的超時時間是一個絕對時間。默認使用系統時間,這意味着若修改系統時間,那麼超時就不準確:有可能提前返回,也可能要幾年才返回。這在某些情況下會導致bug,這時我們可以通過設置條件變量的時鐘屬性來避免這個問題。下面的例子展示了如何使用這個屬性:

Linux C語言pthread_mutex_unlock和pthread_cond_signal順序問題

signal前解鎖是錯誤,順序相當重要,鎖才能保證你整個操作是完全原子,signal只是整個操作的一部分,它不能被分割出去。用特殊一點的情況來解釋:如果解鎖後才signal,那麼有可能信號一直發不出去,因為信號線程一直得到不調度。

C語言如何終止線程?

面只有兩個線程,是生產者/消費者模式,已編譯通過,注釋很詳細。

/* 以生產者和消費者模型問題來闡述Linux線程的控制和通信你

生產者線程將生產的產品送入緩衝區,消費者線程則從中取出產品。

緩衝區有N個,是一個環形的緩衝池。

*/

#include stdio.h

#include pthread.h

#define BUFFER_SIZE 16

struct prodcons

{

int buffer[BUFFER_SIZE];/*實際存放數據的數組*/

pthread_mutex_t lock;/*互斥體lock,用於對緩衝區的互斥操作*/

int readpos,writepos; /*讀寫指針*/

pthread_cond_t notempty;/*緩衝區非空的條件變量*/

pthread_cond_t notfull;/*緩衝區未滿 的條件變量*/

};

/*初始化緩衝區*/

void pthread_init( struct prodcons *p)

{

pthread_mutex_init(p-lock,NULL);

pthread_cond_init(p-notempty,NULL);

pthread_cond_init(p-notfull,NULL);

p-readpos = 0;

p-writepos = 0;

}

/*將產品放入緩衝區,這裡是存入一個整數*/

void put(struct prodcons *p,int data)

{

pthread_mutex_lock(p-lock);

/*等待緩衝區未滿*/

if((p-writepos +1)%BUFFER_SIZE ==p-readpos)

{

pthread_cond_wait(p-notfull,p-lock);

}

p-buffer[p-writepos] =data;

p-writepos++;

if(p-writepos = BUFFER_SIZE)

p-writepos = 0;

pthread_cond_signal(p-notempty);

pthread_mutex_unlock(p-lock);

}

/*從緩衝區取出整數*/

int get(struct prodcons *p)

{

int data;

pthread_mutex_lock(p-lock);

/*等待緩衝區非空*/

if(p-writepos == p-readpos)

{

pthread_cond_wait(p-notempty ,p-lock);//非空就設置條件變量notempty

}

/*讀書據,移動讀指針*/

data = p-buffer[p-readpos];

p-readpos++;

if(p-readpos == BUFFER_SIZE)

p-readpos = 0;

/*設置緩衝區未滿的條件變量*/

pthread_cond_signal(p-notfull);

pthread_mutex_unlock(p-lock);

return data;

}

/*測試:生產站線程將1 到1000的整數送入緩衝區,消費者線程從緩衝區中獲取整數,兩者都打印信息*/

#define OVER (-1)

struct prodcons buffer;

void *producer(void *data)

{

int n;

for( n=0;n1000;n++)

{

printf(“%d ——\n”,n);

put(buffer,n);

}

put(buffer,OVER);

return NULL;

}

void *consumer(void *data)

{

int d;

while(1)

{

d = get(buffer);

if(d == OVER)

break;

else

printf(“—–%d\n”,d);

}

return NULL;

}

int main()

{

pthread_t th_p,th_c;

void *retval;

pthread_init(buffer);

pthread_create(th_p,NULL,producer,0);

pthread_create(th_c,NULL,consumer,0);

/*等待兩個線程結束*/

pthread_join(th_p, retval);

pthread_join(th_c,retval);

return 0;

}

C語言多線程的操作步驟

線程創建

函數原型:intpthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg);

返回值:若是成功建立線程返回0,否則返回錯誤的編號。

形式參數:pthread_t*restrict tidp要創建的線程的線程id指針;const pthread_attr_t *restrict attr創建線程時的線程屬性;void *(start_rtn)(void)返回值是void類型的指針函數;void *restrict arg start_rtn的形參。

線程掛起:該函數的作用使得當前線程掛起,等待另一個線程返回才繼續執行。也就是說當程序運行到這個地方時,程序會先停止,然後等線程id為thread的這個線程返回,然後程序才會斷續執行。

函數原型:intpthread_join(pthread_tthread, void **value_ptr);

參數說明如下:thread等待退出線程的線程號;value_ptr退出線程的返回值。

返回值:若成功,則返回0;若失敗,則返回錯誤號。

線程退出

函數原型:voidpthread_exit(void *rval_ptr);

獲取當前線程id

函數原型:pthread_tpthread_self(void);

互斥鎖

創建pthread_mutex_init;銷毀pthread_mutex_destroy;加鎖pthread_mutex_lock;解鎖pthread_mutex_unlock。

條件鎖

創建pthread_cond_init;銷毀pthread_cond_destroy;觸發pthread_cond_signal;廣播pthread_cond_broadcast;等待pthread_cond_wait。

原創文章,作者:AGRF,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/141295.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
AGRF的頭像AGRF
上一篇 2024-10-04 00:24
下一篇 2024-10-04 01:58

相關推薦

  • AES加密解密算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES算法,並對實現過程進…

    編程 2025-04-29
  • 學習Python對學習C語言有幫助嗎?

    Python和C語言是兩種非常受歡迎的編程語言,在程序開發中都扮演着非常重要的角色。那麼,學習Python對學習C語言有幫助嗎?答案是肯定的。在本文中,我們將從多個角度探討Pyth…

    編程 2025-04-29
  • Python被稱為膠水語言

    Python作為一種跨平台的解釋性高級語言,最大的特點是被稱為”膠水語言”。 一、簡單易學 Python的語法簡單易學,更加人性化,這使得它成為了初學者的入…

    編程 2025-04-29
  • OpenJudge答案1.6的C語言實現

    本文將從多個方面詳細闡述OpenJudge答案1.6在C語言中的實現方法,幫助初學者更好地學習和理解。 一、需求概述 OpenJudge答案1.6的要求是,輸入兩個整數a和b,輸出…

    編程 2025-04-29
  • Python按位運算符和C語言

    本文將從多個方面詳細闡述Python按位運算符和C語言的相關內容,並給出相應的代碼示例。 一、概述 Python是一種動態的、面向對象的編程語言,其按位運算符是用於按位操作的運算符…

    編程 2025-04-29
  • Python語言由荷蘭人為中心的全能編程開發工程師

    Python語言是一種高級語言,很多編程開發工程師都喜歡使用Python語言進行開發。Python語言的創始人是荷蘭人Guido van Rossum,他在1989年聖誕節期間開始…

    編程 2025-04-28
  • Python語言設計基礎第2版PDF

    Python語言設計基礎第2版PDF是一本介紹Python編程語言的經典教材。本篇文章將從多個方面對該教材進行詳細的闡述和介紹。 一、基礎知識 本教材中介紹了Python編程語言的…

    編程 2025-04-28
  • Python語言實現人名最多數統計

    本文將從幾個方面詳細介紹Python語言實現人名最多數統計的方法和應用。 一、Python實現人名最多數統計的基礎 1、首先,我們需要了解Python語言的一些基礎知識,如列表、字…

    編程 2025-04-28
  • Python作為中心語言,在編程中取代C語言的優勢和挑戰

    Python一直以其簡單易懂的語法和高效的編碼環境而著名。然而,它最近的發展趨勢表明Python的使用範圍已經從腳本語言擴展到了從Web應用到機器學習等廣泛的開發領域。與此同時,C…

    編程 2025-04-28
  • Python基礎語言

    Python作為一種高級編程語言擁有簡潔優雅的語法。在本文中,我們將從多個方面探究Python基礎語言的特點以及使用技巧。 一、數據類型 Python基礎數據類型包括整數、浮點數、…

    編程 2025-04-28

發表回復

登錄後才能評論