日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux多线程同步的几种方式

發布時間:2025/3/21 linux 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux多线程同步的几种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程的最大特點是資源的共享性,但資源共享中的同步問題是多線程編程的難點。linux下提供了多種方式來處理線程同步,最常用的是互斥鎖、條件變量和信號量。

1)互斥鎖(mutex)

? ? 通過鎖機制實現線程間的同步。同一時刻只允許一個線程執行一個關鍵部分的代碼。

Cpp代碼 ?
  • int?pthread_mutex_init(pthread_mutex_t?*mutex,const?pthread_mutex_attr_t?*mutexattr);??
  • int?pthread_mutex_lock(pthread_mutex?*mutex);??
  • int?pthread_mutex_destroy(pthread_mutex?*mutex);??
  • int?pthread_mutex_unlock(pthread_mutex?*??
  • ?

    (1)先初始化鎖init()或靜態賦值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIER

    attr_t有:

    PTHREAD_MUTEX_TIMED_NP:其余線程等待隊列

    PTHREAD_MUTEX_RECURSIVE_NP:嵌套鎖,允許線程多次加鎖,不同線程,解鎖后重新競爭

    PTHREAD_MUTEX_ERRORCHECK_NP:檢錯,與一同,線程請求已用鎖,返回EDEADLK;

    PTHREAD_MUTEX_ADAPTIVE_NP:適應鎖,解鎖后重新競爭

    (2)加鎖,lock,trylock,lock阻塞等待鎖,trylock立即返回EBUSY

    (3)解鎖,unlock需滿足是加鎖狀態,且由加鎖線程解鎖

    (4)清除鎖,destroy(此時鎖必需unlock,否則返回EBUSY,//Linux下互斥鎖不占用內存資源

    示例代碼

    Cpp代碼 ?
  • #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()???
  • {???
  • ????//如果不用<span?style="font-size:?1em;?line-height:?1.5;">PTHREAD_MUTEX_INITIALIZER,可以使用</span>pthread_mutex_init(&mutex,?NULL);??
  • ????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

    說明:pthread庫不是Linux系統默認的庫,連接時需要使用靜態庫libpthread.a,所以在使用pthread_create()創建線程,以及調用pthread_atfork()函數建立fork處理程序時,需要鏈接該庫。在編譯中要加 -lpthread參數。

    ?

    2)條件變量(cond)

    ? ? 利用線程間共享的全局變量進行同步的一種機制。條件變量上的基本操作有:觸發條件(當條件變為 true 時);等待條件,掛起線程直到其他線程觸發條件。

    Cpp代碼 ?
  • int?pthread_cond_init(pthread_cond_t?*cond,pthread_condattr_t?*cond_attr);?????
  • 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);??
  • int?pthread_cond_destroy(pthread_cond_t?*cond);??
  • int?pthread_cond_signal(pthread_cond_t?*cond);??
  • int?pthread_cond_broadcast(pthread_cond_t?*cond);??//解除所有線程的阻塞??
  • ?

    (1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER(前者為動態初始化,后者為靜態初始化);屬性置為NULL

    (2)等待條件成立.pthread_wait,pthread_timewait.wait()釋放鎖,并阻塞等待條件變量為真,timewait()設置等待時間,仍未signal,返回ETIMEOUT(加鎖保證只有一個線程wait)

    (3)激活條件變量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待線程)

    (4)清除條件變量:destroy;無線程等待,否則返回EBUSY

    對于

    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

    int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

    一定要在mutex的鎖定區域內使用。

    ? ? 如果要正確的使用pthread_mutex_lock與pthread_mutex_unlock,請參考

    pthread_cleanup_push和pthread_cleanup_pop宏,它能夠在線程被cancel的時候正確的釋放mutex!

    ? ? 另外,posix1標準說,pthread_cond_signal與pthread_cond_broadcast無需考慮調用線程是否是mutex的擁有者,也就是說,可以在lock與unlock以外的區域調用。如果我們對調用行為不關心,那么請在lock區域之外調用吧。

    說明:

    ? ? (1)pthread_cond_wait 自動解鎖互斥量(如同執行了pthread_unlock_mutex),并等待條件變量觸發。這時線程掛起,不占用CPU時間,直到條件變量被觸發(變量為ture)。在調用 pthread_cond_wait之前,應用程序必須加鎖互斥量。pthread_cond_wait函數返回前,自動重新對互斥量加鎖(如同執行了pthread_lock_mutex)。

    ? ? (2)互斥量的解鎖和在條件變量上掛起都是自動進行的。因此,在條件變量被觸發前,如果所有的線程都要對互斥量加鎖,這種機制可保證在線程加鎖互斥量和進入等待條件變量期間,條件變量不被觸發。條件變量要和互斥量相聯結,以避免出現條件競爭——個線程預備等待一個條件變量,當它在真正進入等待之前,另一個線程恰好觸發了該條件(條件滿足信號有可能在測試條件和調用pthread_cond_wait函數(block)之間被發出,從而造成無限制的等待)。

    (3)pthread_cond_timedwait 和 pthread_cond_wait 一樣,自動解鎖互斥量及等待條件變量,但它還限定了等待時間。如果在abstime指定的時間內cond未觸發,互斥量mutex被重新加鎖,且pthread_cond_timedwait返回錯誤 ETIMEDOUT。abstime 參數指定一個絕對時間,時間原點與 time 和 gettimeofday 相同:abstime = 0 表示 1970年1月1日00:00:00 GMT。

    (4)pthread_cond_destroy 銷毀一個條件變量,釋放它擁有的資源。進入 pthread_cond_destroy 之前,必須沒有在該條件變量上等待的線程。

    ? ? (5)條件變量函數不是異步信號安全的,不應當在信號處理程序中進行調用。特別要注意,如果在信號處理程序中調用 pthread_cond_signal 或 pthread_cond_boardcast 函數,可能導致調用線程死鎖。

    示例程序1

    Cpp代碼 ?
  • #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;??
  • }??
  • ??

    ?

    示例程序2:

    Cpp代碼 ?
  • #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;???
  • ???
  • /*[thread_func]*/???
  • 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);,再讀取資源???
  • ?????????//用這個流程是比較清楚的/*block-->unlock-->wait()?return-->lock*/???
  • ?????????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;???
  • }??
  • ?

    3)信號量

    ? ? 如同進程一樣,線程也可以通過信號量來實現通信,雖然是輕量級的。

    ? ? 信號量函數的名字都以"sem_"打頭。線程使用的基本信號量函數有四個。

    #include <semaphore.h>

    int sem_init (sem_t *sem , int pshared, unsigned int value);

    ? ? 這是對由sem指定的信號量進行初始化,設置好它的共享選項(linux 只支持為0,即表示它是當前進程的局部信號量),然后給它一個初始值VALUE。

    兩個原子操作函數:

    int sem_wait(sem_t *sem);

    int sem_post(sem_t *sem);

    ? ? 這兩個函數都要用一個由sem_init調用初始化的信號量對象的指針做參數。

    sem_post:給信號量的值加1;

    sem_wait:給信號量減1;對一個值為0的信號量調用sem_wait,這個函數將會等待直到有其它線程使它不再是0為止。

    int sem_destroy(sem_t *sem);

    ? ? 這個函數的作用是再我們用完信號量后都它進行清理。歸還自己占有的一切資源。

    ?

    示例代碼:

    Cpp代碼 ?
  • #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;???
  • }??
  • ??

    ?

    通 過執行結果后,可以看出,會先執行線程二的函數,然后再執行線程一的函數。它們兩就實現了同步。在上大學的時候,雖然對這些概念知道,可都沒有實踐過,所 以有時候時間一久就會模糊甚至忘記,到了工作如果還保持這么一種狀態,那就太可怕了。雖然現在外面的技術在不斷的變化更新,可是不管怎么變,其核心技術還 是依舊的,所以我們必須要打好自己的基礎,再學習其他新的知識,那時候再學新的知識也會覺得比較簡單的。信號量代碼摘自http://blog.csdn.net/wtz1985/article/details/3835781

    參考:

    【1】 http://www.cnblogs.com/feisky/archive/2009/11/12/1601824.html

    【2】 http://www.cnblogs.com/mydomain/archive/2011/07/10/2102147.html

    【3】 線程函數介紹

    http://www.unix.org/version2/whatsnew/threadsref.html

    【4】 http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

    【5】 線程常用函數簡介

    http://www.rosoo.net/a/201004/8954.html

    【6】 條件變量

    http://blog.csdn.net/hiflower/article/details/2195350

    【7】條件變量函數說明

    http://blog.csdn.net/hairetz/article/details/4535920

    總結

    以上是生活随笔為你收集整理的Linux多线程同步的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 在线看日本 | 一二区在线观看 | 欧美乱轮 | 可以免费看黄的网站 | 国产在线视频福利 | 亚洲aaaaaaa| 打白嫩屁屁网站视频短裙 | 亚洲三区在线 | 欧美日韩一区二区三区电影 | 久久社区视频 | 懂色av蜜臀av粉嫩av分享吧 | 亚洲国产精品毛片av不卡在线 | 国产经典毛片 | 电家庭影院午夜 | 精品国产美女 | 久久久久久久美女 | 国产精视频 | 男女做爰真人视频直播 | 日韩亚洲在线 | 国产精品视频麻豆 | com国产| 成人免费黄色网 | 国产麻豆91视频 | 丁香啪啪综合成人亚洲 | 综合视频在线 | 亚洲啪视频 | 久久久av片 | 国产精品自慰网站 | www视频免费在线观看 | 狠狠躁夜夜躁 | 午夜视频免费观看 | 久久久久逼 | 久久最新视频 | 中文字幕无码毛片免费看 | 亚洲黄色网络 | 小泽玛利亚一区二区三区 | 成人在线视频一区 | 4444亚洲人成无码网在线观看 | 台湾佬美性中文娱乐网 | 九九综合久久 | 视频污在线观看 | 欧美一级片网址 | 国产伦理片在线观看 | 激情一区 | 老司机成人网 | 91福利专区 | 色综合图片区 | 麻豆视频网站入口 | 人人艹人人 | 久久久久免费观看 | 久久精品无码Av中文字幕 | 午夜黄色av | 成人动漫免费在线观看 | 久久久久久久久免费视频 | 天天干天天操天天插 | 日韩黄色网 | av图区 | 国产有码| 成人在线国产精品 | 久久精品中文闷骚内射 | 免费一区二区三区四区 | 波多野结衣日韩 | 人人妻人人澡人人爽 | 国产成人在线电影 | japanesexxxx日本妞| www.youjizz.com中国 | 免费成人小视频 | 欧美成人手机在线 | 欧美精品一级片 | 中文字幕在线欧美 | 四虎成人网 | 黑人操白妞 | 日本黄色片. | 国产区久久 | 国产ts在线 | 人妻在线一区 | 国产一区二区福利 | 香蕉免费在线视频 | 尤物国产视频 | 嫩草影院一区二区三区 | 欧美日韩精品一区 | 久久av秘一区二区三区 | 欧美日韩国产成人 | 美女视频久久 | 国产精品精品久久久久久 | 五月天婷婷色 | 天堂av在线免费观看 | 欧美一二三四五区 | 成人免费在线播放 | 97超级碰碰人妻中文字幕 | 亚洲另类欧美日韩 | 激情一区二区三区 | 国产精品久久久久久久毛片 | 日本黄色录像片 | 亚洲网站视频 | 成人精品一区二区三区电影 | 中文字幕永久免费 | 男生坤坤放进女生坤坤里 | 涩涩资源网 |