臨界資源:
樂山網站制作公司哪家好,找成都創(chuàng)新互聯!從網頁設計、網站建設、微信開發(fā)、APP開發(fā)、成都響應式網站建設等網站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯自2013年創(chuàng)立以來到現在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選成都創(chuàng)新互聯。
一個進程的資源對于運行在它內部的線程是共享的,一次只允許一個線程使用的資源叫做臨界資源
臨界區(qū):
訪問臨界資源的那段程序叫做臨界區(qū)
線程的同步:
同步就是協同步調,按照預定的先后順序執(zhí)行。
“同”字應是指協同、協助、互相配合。
線程的互斥:
某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。
但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
互斥量(mutex)
多個線程同時訪問共享數據時,經常會發(fā)生沖突,因此常常引入互斥鎖來解決這個問題。
沖突:例如對一個全局變量g_var進行加一操作,這樣的操作需要三條指令來完成:(1、把該變量的值從內存讀到寄存器;2、寄存器進行加一操作;3、把修改后的值寫回內存),因為這三條指令的執(zhí)行不是原子操作,有可能線程1執(zhí)行了第一步(把變量值讀到寄存器),此時內核調度線程2,線程2也把該值讀到寄存器,它們都進行加一操作后寫回內存,導致最后結果只加了一次,而我們希望是兩次。
解決:引入互斥鎖,獲得鎖的線程可以對變量進行“讀-修改-寫”操作,這個操作是原子的,完成這個操作后釋放鎖給別的線程,沒有獲得鎖的線程只能等待而不能訪問該共享數據。
有關函數:
1.互斥鎖的初始化及銷毀
其中初始化既可以使用函數pthread_mutex_init(),也可以定義pthread_mutex_t類型的變量mutex,并賦值PTHREAD_MUTEX_INITIALIZER
2.對mutex的加鎖及解鎖
一個線程可以調用pthread_mutex_lock獲得Mutex,如果這時另一個線程已經調用pthread_mutex_lock獲得了該Mutex,則當前線程需要掛起等待,直到另一個線程調用pthread_mutex_unlock釋放Mutex,當前線程被喚醒,才能獲得該Mutex并繼續(xù)執(zhí)行。
如果一個線程既想獲得鎖,又不想掛起等待,可以調用pthread_mutex_trylock,如果Mutex已經被另一個線程獲得,這個函數會失敗返回EBUSY,而不會使線程掛起等待。
Mutex的lock和unlock的偽碼(以x86的xchg指令為例):
不使用互斥量代碼:
#include <stdio.h> #include <pthread.h> void *thread(void *arg) { int count=2000; while(count-- >0){ int var=g_var; printf("this is thread%d,g_var=%d\n",(int)arg,g_var); g_var=var+1; } } int main() { pthread_t tid1,tid2; if(pthread_create(&tid1,NULL,thread,(void*)1)!=0){ printf("creat tid1 is failed\n"); } if(pthread_create(&tid1,NULL,thread,(void*)2)!=0){ printf("creat tid1 is failed\n"); } pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; }
運行結果:
第一次運行線程1和線程2一共加了2275次
第二次運行一共把g_var加了2000次
使用互斥量實現代碼:
include <stdio.h> #include <pthread.h> //pthread_mutex_t mutex_lock=PTHREAD_MUTEX_INITIALIZER; struct info { int _var; pthread_mutex_t *_mutex_lock; }info; int g_var=0; void *thread(void *arg) { struct info* _lock=(struct info*)arg; int count=2000; while(count-- >0){ pthread_mutex_lock(_lock->_mutex_lock); int var=g_var; printf("this is thread%d,g_var=%d\n",_lock->_var,g_var); g_var=var+1; pthread_mutex_unlock(_lock->_mutex_lock); } } int main() { pthread_t tid1,tid2; pthread_mutex_t mutex_lock; int err=pthread_mutex_init(&mutex_lock,NULL); if(err!=0){ printf("%s\n",strerror(err)); } struct info info1; info1._var=1; info1._mutex_lock=&mutex_lock; if(pthread_create(&tid1,NULL,thread,&info1)!=0){ printf("creat tid1 is failed\n"); } struct info info2; info2._var=2; info2._mutex_lock=&mutex_lock; if(pthread_create(&tid2,NULL,thread,&info2)!=0){ printf("creat tid2 is failed\n"); } pthread_join(tid1,NULL); pthread_join(tid2,NULL); err=pthread_mutex_destroy(&mutex_lock); if(err!=0){ printf("%s\n",strerror(err)); } return 0; }
運行結果:
線程1和線程2共執(zhí)行了4000次
總結:當一個線程已經獲得鎖,另一個線程需掛起等待,當該線程釋放鎖后,會喚醒正在等待線程。每個mutex都有一個等待隊列,當線程掛起時,就加入該等待隊列,狀態(tài)設置為睡眠。一個線程要喚醒別的線程,只需要從等待隊列中取出一項加入就緒隊列并把它的狀態(tài)設置為就緒。
有的時候一個線程會兩次獲得鎖,第一次正常獲得,第二次獲得所得時候發(fā)現鎖已經被別占用,它就會掛起,導致自己占用了鎖卻處于掛起狀態(tài),這樣就產生了死鎖。
死鎖:
產生死鎖的原因
1、進程資源不足
2、進程推進的順序不合適
3、系統資源的分配不當
產生死鎖的必要條件:
1、互斥條件:一個資源一次只能被一個進程使用
2、請求與保持條件:一個已經進程因請求資源而阻塞,對已獲得的資源保持不放
3、不剝奪條件:進程已獲得的資源,在沒使用完之前,不能強行剝奪
4、循環(huán)等待條件:若干個進程之間形成一種頭尾相接的循環(huán)等待資源關系
產生死鎖時,以上四個必要條件一定都成立。
網頁名稱:線程同步與互斥(死鎖的避免)
瀏覽路徑:http://muchs.cn/article8/ijdgop.html
成都網站建設公司_創(chuàng)新互聯,為您提供虛擬主機、App設計、搜索引擎優(yōu)化、網頁設計公司、關鍵詞優(yōu)化、營銷型網站建設
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯