亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

信號量、互斥鎖,讀寫鎖和條件變量的區別

2024-06-28 14:32:12
字體:
來源:轉載
供稿:網友

信號量強調的是線程(或進程)間的同步:“信號量用在多線程多任務同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進行某些動作(大家都
在sem_wait的時候,就阻塞在那里)。當信號量為單值信號量是,也可以完成一個資源的互斥訪問。
有名信號量:可以用于不同進程間或多線程間的互斥與同步
創建打開有名信號量
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
成功返回信號量指針;失敗返回SEM_FAILED,設置errno
name是文件路徑名,但不能寫成/tmp/a.sem這樣的形式,因為在linux下,sem都是在/dev/shm目錄下,可寫成"/mysem"或"mysem",創建出來的文件都
是"/dev/shm/sem.mysem",mode設置為0666,value設置為信號量的初始值.所需信號燈等已存在條件下指定
O_CREAT|O_EXCL卻是個錯誤。
關閉信號量,進程終止時,會自動調用它
int sem_close(sem_t *sem);
成功返回0;失敗返回-1,設置errno
刪除信號量,立即刪除信號量名字,當其他進程都關閉它時,銷毀它
int sem_unlink(const char *name);
等待信號量,測試信號量的值,如果其值小于或等于0,那么就等待(阻塞);一旦其值變為大于0就將它減1,并返回
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
成功返回0;失敗返回-1,設置errno
當信號量的值為0時,sem_trywait立即返回,設置errno為EAGAIN。如果被某個信號中斷,sem_wait會過早地返回,設置errno為EINTR

發出信號量,給它的值加1,然后喚醒正在等待該信號量的進程或線程
int sem_post(sem_t *sem);
成功返回0;失敗返回-1,不會改變它的值,設置errno,該函數是異步信號安全的,可以在信號處理程序里調用它

無名信號量,用于進程體內各線程間的互斥和同步,使用如下API(無名信號量,基于內存的信號量)
(1)、sem_init
功能:用于創建一個信號量,并初始化信號量的值。
頭文件:
函數原型: int sem_init (sem_t* sem, int pshared, unsigned int value);
函數傳入值: sem:信號量。pshared:決定信號量能否在幾個進程間共享。由于目前LINUX還沒有實現進程間共享信息量,所以這個值只能取0。
(2)其他函數。
int sem_wait (sem_t* sem);
int sem_trywait (sem_t* sem);
int sem_post (sem_t* sem);
int sem_getvalue (sem_t* sem);
int sem_destroy (sem_t* sem);
功能:sem_wait和sem_trywait相當于P操作,它們都能將信號量的值減一,兩者的區別在于若信號量的值小于零時,sem_wait將會阻塞進程,而sem_trywait則會立即返回
。sem_post相當于V操作,它將信號量的值加一,同時發出喚醒的信號給等待
的進程(或線程)。
sem_getvalue 得到信號量的值。
sem_destroy 摧毀信號量。
如果某個基于內存的信號燈是在不同進程間同步的,該信號燈必須存放在共享內存區中,這要只要該共享內存區存在,該信號燈就存在。

互斥鎖(又名互斥量)強調的是資源的訪問互斥:互斥鎖是用在多線程多任務互斥的,一個線程占用了某一個資源,那么別的線程就無法訪問,直到這個線程unlock,其他的
線程才開始可以利用這個資源。比如對全局變量的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和信號量會同時使用的”
也就是說,信號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個線程,B線程要等A線程完成某一任務以后再進行自己下面的步驟,這個任務并不一定是鎖
定某一資源,還可以是進行一些計算或者數據處理之類。而線程互斥量則是“鎖住某一資源”的概念,在鎖定期間內,其他線程無法對被保護的數據進行操作。在有些情況
下兩者可以互換。
在linux下, 線程的互斥量數據類型是pthread_mutex_t. 在使用前, 要對它進行初始化:
對于靜態分配的互斥量, 可以把它設置為PTHREAD_MUTEX_INITIALIZER, 或者調用pthread_mutex_init.
對于動態分配的互斥量, 在申請內存(malloc)之后, 通過pthread_mutex_init進行初始化, 并且在釋放內存(free)前需要調用pthread_mutex_destroy.
原型:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
頭文件:
返回值: 成功則返回0, 出錯則返回錯誤編號.
說明: 如果使用默認的屬性初始化互斥量, 只需把attr設為NULL. 其他值在以后講解.
首先說一下加鎖函數:
頭文件:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
返回值: 成功則返回0, 出錯則返回錯誤編號.
說 明: 具體說一下trylock函數, 這個函數是非阻塞調用模式, 也就是說, 如果互斥量沒被鎖住, trylock函數將把互斥量加鎖, 并獲得對共享資源的訪問權限; 如果互斥量
被鎖住了, trylock函數將不會阻塞等待而直接返回EBUSY, 表示共享資源處于忙狀態.
再說一下解所函數:
頭文件:
原型: int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值: 成功則返回0, 出錯則返回錯誤編號.
條件變量常與互斥鎖同時使用,達到線程同步的目的:條件變量通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足。在發 送信號時,如果沒有線程
等待在該條件變量上,那么信號將丟失;而信號量有計數值,每次信號量post操作都會被記錄

1. 互斥鎖必須是誰上鎖就由誰來解鎖,而信號量的wait和post操作不必由同一個線程執行。
2. 互斥鎖要么被鎖住,要么被解開,和二值信號量類似
3. sem_post是各種同步技巧中,唯一一個能在信號處理程序中安全調用的函數
4. 互斥鎖是為上鎖而優化的;條件變量是為等待而優化的; 信號量既可用于上鎖,也可用于等待,因此會有更多的開銷和更高的復雜性
5. 互斥鎖,條件變量都只用于同一個進程的各線程間,而信號量(有名信號量)可用于不同進程間的同步。當信號量用于進程間同步時,要求信號量建立在共享內存區。
6. 信號量有計數值,每次信號量post操作都會被記錄,而條件變量在發送信號時,如果沒有線程在等待該條件變量,那么信號將丟失。

讀寫鎖
  讀寫鎖與互斥量類似,不過讀寫鎖允許更高的并行性?;コ饬恳词擎i住狀態要么是不加鎖狀態,而且一次只有一個線程可以對其加鎖。
  讀寫鎖可以由三種狀態:讀模式下加鎖狀態、寫模式下加鎖狀態、不加鎖狀態。一次只有一個線程可以占有寫模式的讀寫鎖,但是多個線程可以同時占有讀模式的讀寫
鎖。
  在讀寫鎖是寫加鎖狀態時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞。當讀寫鎖在讀加鎖狀態時,所有試圖以讀模式對它進行加鎖的線程都可以
得到訪問權,但是如果線程希望以寫模式對此鎖進行加鎖,它必須阻塞直到所有的線程釋放讀鎖。雖然讀寫鎖的實現各不相同,但當讀寫鎖處于讀模式鎖住狀態時,如果有
另外的線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨后的讀模式鎖請求。這樣可以避免讀模式鎖長期占用,而等待的寫模式鎖請求一直得不到滿足。
  讀寫鎖非常適合于對數據結構讀的次數遠大于寫的情況。當讀寫鎖在寫模式下時,它所保護的數據結構就可以被安全地修改,因為當前只有一個線程可以在寫模式下擁
有這個鎖。當讀寫鎖在讀狀態下時,只要線程獲取了讀模式下的讀寫鎖,該鎖所保護的數據結構可以被多個獲得讀模式鎖的線程讀取。
  讀寫鎖也叫做共享-獨占鎖,當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當他以寫模式鎖住時,它是以獨占模式鎖住的。
初始化和銷毀:
#include
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

成功則返回0, 出錯則返回錯誤編號.
同互斥量以上, 在釋放讀寫鎖占用的內存之前, 需要先通過pthread_rwlock_destroy對讀寫鎖進行清理工作, 釋放由init分配的資源.
讀和寫:
#include
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
成功則返回0, 出錯則返回錯誤編號.
這3個函數分別實現獲取讀鎖, 獲取寫鎖和釋放鎖的操作. 獲取鎖的兩個函數是阻塞操作,
同樣, 非阻塞的函數為:
#include
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

成功則返回0, 出錯則返回錯誤編號.
非阻塞的獲取鎖操作, 如果可以獲取則返回0, 否則返回錯誤的EBUSY.
雖然讀寫鎖提高了并行性,但是就速度而言并不比互斥量快.
可能這也是即使有讀寫鎖存在還會使用互斥量的原因,因為他在速度方面略勝一籌。這就需要我們在寫程序的時候
綜合考慮速度和并行性并找到一個折中。
比如: 假設使用互斥量需要0.5秒,使用讀寫鎖需要0.8秒。在類似學生管理系統這類軟件中,可能百分之九十的
時間都是查詢操作,那么假如現在突然來個個20個請求,如果使用的是互斥量,那么最后的那個查詢請求被滿足需要10后。這樣,估計沒人能受得了。而使用讀寫鎖,應為
讀鎖能夠多次獲得。所以所有的20個請求,每個請求都能在1秒左右
得到滿足。
也就是說,在一些寫操作比較多或是本身需要同步的地方并不多的程序中我們應該使用互斥量,而在讀操作遠大于寫操作的一些程序中我們應該使用讀寫鎖來進行同步

條件變量(condition)
  條件變量與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發生。
  條件本身是由互斥量保護的。線程在改變條件狀態前必須首先鎖住互斥量,其它線程在獲得互斥量之前不會察覺到這種改變,因此必須鎖定互斥量以后才能計算條件。
條件的檢測是在互斥鎖的保護下進行的。如果一個條件為假,一個線程自動阻塞,并釋放等待狀態改變的互斥鎖。如果另一個線程改變了條件,它發信號給關聯的條件
變量,喚醒一個或多個等待它的線程,重新獲得互斥鎖,重新評價條件。如果兩進程共享可讀寫的內存,條件變量可以被用來實現這兩進程間的線程同步。
1. 初始化:
條件變量采用的數據類型是pthread_cond_t, 在使用之前必須要進行初始化, 這包括兩種方式:
靜態: 可以把常量PTHREAD_COND_INITIALIZER給靜態分配的條件變量.
動態: pthread_cond_init函數, 是釋放動態條件變量的內存空間之前, 要用pthread_cond_destroy對其進行清理.
#include
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
成功則返回0, 出錯則返回錯誤編號.
注意:條件變量占用的空間并未被釋放。
當pthread_cond_init的attr參數為NULL時, 會創建一個默認屬性的條件變量; 非默認情況以后討論.
2. 等待條件:
#include
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

成功則返回0, 出錯則返回錯誤編號.
這兩個函數分別是阻塞等待和超時等待.
等待條件函數等待條件變為真, 傳遞給pthread_cond_wait的互斥量對條件進行保護, 調用者把鎖住的互斥量傳遞給函數. 函數把調用線程放到等待條件的線程列表上,
然后對互斥量解鎖, 這兩個操作是原子的. 這樣 便關閉了條件檢查和線程進入休眠狀態等待條件改變這兩個操作之間的時間通道, 這樣線程就不會錯過條件的任何變化.
當pthread_cond_wait返回時, 互斥量再次被鎖住.
pthread_cond_wait函數的返回并不意味著條件的值一定發生了變化,必須重新檢查條件的值。

pthread_cond_wait函數返回時,相應的互斥鎖將被當前線程鎖定,即使是函數出錯返回。

阻塞在條件變量上的線程被喚醒以后,直到pthread_cond_wait()函數返回之前條件的值都有可能發生變化。所以函數返回以后,在鎖定相應的互斥鎖之前,必須重新測試條
件值。最好的測試方法是循環調用pthread_cond_wait函數,并把滿足條件的表達式置為循環的終止條件。如:

pthread_mutex_lock();

while (condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();

阻塞在同一個條件變量上的不同線程被釋放的次序是不一定的。

注意:pthread_cond_wait()函數是退出點,如果在調用這個函數時,已有一個掛起的退出請求,且線程允許退出,這個線程將被終止并開始執行善后處理函數,而這時和條
件變量相關的互斥鎖仍將處在鎖定狀態。
pthread_cond_timedwait函數到了一定的時間,即使條件未發生也會解除阻塞。這個時間由參數abstime指定。函數返回時,相應的互斥鎖往往是鎖定的,即使是函數出錯返
回。

注意:pthread_cond_timedwait函數也是退出點。

超時時間參數是指一天中的某個時刻。使用舉例:

pthread_timestruc_t to;

to.tv_sec = time(NULL) + TIMEOUT;

to.tv_nsec = 0;

超時返回的錯誤碼是ETIMEDOUT。


3. 通知條件:
#include
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
成功則返回0, 出錯則返回錯誤編號.
這兩個函數用于通知線程條件已經滿足. 調用這兩個函數, 也稱向線程或條件發送信號. 必須注意, 一定要在改變條件狀態以后再給線程發送信號.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩视频在线免费观看| 亚洲精品小视频在线观看| 欧美国产日韩在线| 国产视频欧美视频| 97香蕉超级碰碰久久免费的优势| 国产精品mp4| 国产成人avxxxxx在线看| 久久久久久午夜| 久久久久女教师免费一区| 国内精品视频一区| 国产精品自产拍在线观| 日韩免费观看在线观看| 91久久嫩草影院一区二区| 亚洲国产成人精品久久久国产成人一区| 91精品国产99| 国产精品福利观看| 亚洲韩国青草视频| 国产精品91久久久| 欧美激情一区二区三区在线视频观看| 欧美午夜精品久久久久久久| 国产日韩欧美黄色| 成人情趣片在线观看免费| 国产精品久久久久久久久影视| 日韩www在线| 国产精品99蜜臀久久不卡二区| 成人做爽爽免费视频| 国产91露脸中文字幕在线| 国产欧美一区二区三区久久人妖| 欧美成人sm免费视频| 亚洲精品欧美日韩专区| 亚洲精品色婷婷福利天堂| 在线观看欧美视频| 国产精品草莓在线免费观看| 欧美激情精品久久久久久| 日韩电影免费在线观看| 欧美午夜女人视频在线| 欧美www在线| 最新69国产成人精品视频免费| 亚洲第一精品夜夜躁人人躁| 九九热这里只有精品免费看| 国产精品久久久久久久久免费| 欧美中文字幕精品| 亚洲欧美国产高清va在线播| 日韩一区二区久久久| 国自产精品手机在线观看视频| 国产精品69精品一区二区三区| 国模叶桐国产精品一区| 久久久国产精品一区| 亚洲男子天堂网| 成人福利视频在线观看| 萌白酱国产一区二区| 久操成人在线视频| 欧美另类第一页| 18一19gay欧美视频网站| 精品精品国产国产自在线| 国产精品免费看久久久香蕉| 亚洲欧美日韩一区二区三区在线| 日韩精品免费一线在线观看| 欧美电影免费播放| 欧洲成人免费视频| 26uuu亚洲伊人春色| 欧美性猛交xxxx免费看| 国产日产欧美a一级在线| 国产丝袜一区二区三区免费视频| 国产69精品久久久久久| 亚洲一区av在线播放| 激情成人在线视频| 精品福利在线看| 久久影视三级福利片| 成人精品视频99在线观看免费| 日韩欧美一区视频| 久久国产精品久久久久久久久久| 日韩美女中文字幕| 国产中文字幕91| 91嫩草在线视频| 久久久久久久91| 欧美中文字幕在线观看| 在线观看久久久久久| 欧美在线观看日本一区| 亚洲欧洲在线视频| 日韩久久精品成人| 欧美成人中文字幕在线| 午夜精品免费视频| 97精品欧美一区二区三区| 精品福利视频导航| 久久影院在线观看| 91九色国产在线| 26uuu日韩精品一区二区| 国产精品久久激情| 日韩av在线看| 欧美激情影音先锋| 亚洲激情视频在线| 国产精品69久久| 久久成人精品一区二区三区| 欧美一区亚洲一区| 5278欧美一区二区三区| 欧美精品videosex极品1| 国产精品免费久久久久影院| 成人看片人aa| 日韩小视频网址| 色噜噜国产精品视频一区二区| 中文国产亚洲喷潮| 亚洲成人激情在线| 欧美激情亚洲视频| 欧美在线视频免费播放| 国产第一区电影| 日韩福利在线播放| 97国产真实伦对白精彩视频8| 日韩欧美高清视频| 久久亚洲私人国产精品va| 亚洲变态欧美另类捆绑| 欧美性生活大片免费观看网址| 久久精品国产亚洲精品2020| 欧美日韩国产黄| 中文字幕日韩专区| 日韩黄色在线免费观看| 亚洲精品98久久久久久中文字幕| 国产精品永久免费在线| 国产日韩换脸av一区在线观看| 久久久精品国产网站| 国产91成人video| 亚洲午夜性刺激影院| 2019最新中文字幕| 亚洲欧美一区二区三区四区| 日韩av在线天堂网| 6080yy精品一区二区三区| 亚洲自拍偷拍福利| 精品国产鲁一鲁一区二区张丽| 欧美日韩免费一区| 久久精品国亚洲| 亚洲精品98久久久久久中文字幕| 国产精品福利久久久| 成人做爰www免费看视频网站| 国产中文字幕91| 一个色综合导航| 国产日韩中文在线| 国产精品黄色影片导航在线观看| 久久在精品线影院精品国产| 久久久久久久久久国产精品| 国产精品99久久久久久人| 久久精品久久久久电影| 国产在线精品自拍| 精品视频9999| 久久精品国产一区二区三区| 精品国产福利视频| 亚洲精品www久久久久久广东| 成人免费在线视频网址| 美女国内精品自产拍在线播放| 欧美激情网友自拍| 亚洲免费福利视频| 国产精品视频一| 国产精品一区二区久久精品| 57pao精品| 日韩精品在线视频观看| 亚洲精品欧美一区二区三区| 亚洲精品电影在线| 日韩欧美精品免费在线| 7777精品视频| 亚洲第一页在线| 伊人激情综合网| 国产精品福利在线观看| 亚洲一区亚洲二区| 亚洲精品99久久久久中文字幕| 91tv亚洲精品香蕉国产一区7ujn|