1线程同步:互斥量,死锁
1線程為什么要同步
A:共享資源,多個線程都可對共享資源操作。
B:線程操作共享資源的先后順序不確定。
C:處理器對存儲器的操作一般不是原子操作。
2互斥量
mutex操作原語
pthread_mutex_t
pthread_mutex_init
pthread_mutex_destroy
pthread_mutex_lock
pthread_mutex_trylock
pthread_mutex_unlock
3臨界區(Critical Section)
保證在某一時刻只有一個線程能訪問數據的簡便辦法。在任意時刻只允許一個線程對共享資源進行訪問。如果有多個線程試圖同時訪問臨界區,那么在有一個線程進入后其他所有試圖訪問此臨界區的線程將被掛起,并一直持續到進入臨界區的線程離開。臨界區在被釋放后,其他線程可以繼續搶占,并以此達到用原子方式操作共享資源的目的。
4臨界區的選定
???臨界區的選定應盡可能小,如果選定太大會影響程序的并行處理性能。
5互斥量實例
依賴的頭文件
#include<pthread.h>
函數聲明
int pthread_mutex_destroy(pthread_mutex_t*mutex);
| 名稱: | pthread_mutex_destroy |
| 功能: | 釋放對互斥變量分配的資源 |
| 頭文件: | #include <pthread.h> |
| 函數原形: | int? pthread_mutex_destroy(pthread_mutex_t *mutex); |
| 參數: | ? |
| 返回值: | 若成功則返回0,否則返回錯誤編號。 |
?
int pthread_mutex_init(pthread_mutex_t*restrict mutex, const pthread_mutexattr_t *restrict attr);
| 名稱: | pthread_mutexattr_init |
| 功能: | 初始化互斥鎖。 |
| 頭文件: | #include <pthread.h> |
| 函數原形: | int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutex_t *attr); |
| 參數: | mutex?互斥量 attr????互斥鎖屬性 |
| 返回值: | 若成功則返回0,否則返回錯誤編號。 |
int pthread_mutex_lock(pthread_mutex_t*mutex);
int pthread_mutex_trylock(pthread_mutex_t*mutex);
int pthread_mutex_unlock(pthread_mutex_t*mutex);
| 名稱: | pthread_mutex_lock/ pthread_mutex_trylock/ pthread_mutex_unlock |
| 功能: | 對互斥量加/減鎖 |
| 頭文件: | #include <pthread.h> |
| 函數原形: | int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); |
| 參數: | ? |
| 返回值: | 若成功則返回0,否則返回錯誤編號。 |
函數說明:
對互斥量進行加鎖,需要調用pthread_mutex_lock,如果互斥量已經上鎖,調用線程阻塞直至互斥量解鎖。對互斥量解鎖,需要調用pthread_mutex_unlock.
??????如果線程不希望被阻塞,他可以使用pthread_mutex_trylock嘗試對互斥量進行加鎖。如果調用pthread_mutex_trylock時互斥量處于未鎖住狀態,那么pthread_mutex_trylock將鎖住互斥量,否則就會失敗,不能鎖住互斥量,而返回EBUSY。
?
6互斥鎖創建
有兩種方法創建互斥鎖,靜態方式和動態方式。
A:POSIX定義了一個宏PTHREAD_MUTEX_INITIALIZER來靜態初始化互斥鎖,方法如下:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
B:動態方式是采用pthread_mutex_init()函數來初始化互斥鎖,API定義如下:
int pthread_mutex_init(pthread_mutex_t *mutex, constpthread_mutexattr_t *mutexattr);
其中mutexattr用于指定互斥鎖屬性,如果為NULL則使用缺省屬性。
C:pthread_mutex_destroy ()用于注銷一個互斥鎖,API定義如下:
???intpthread_mutex_destroy(pthread_mutex_t *mutex);
D:pthread_mutex_lock()加鎖
E:pthread_mutex_unlock()解鎖
F:pthread_mutex_trylock()測試加鎖
G:釋放內存前需要調用pthread_mutex_destory.
案例說明互斥量加鎖的必要性:
| #include<stdio.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> ? void *thread_function(void *arg); /*用run_now代表共享資源*/ int run_now = 1; ? int main(void) { ???int print_count1 = 0;/*用于循環控制*/ ???pthread_t a_thread; ? ???/*創建一個進程*/ ???if(pthread_create(&a_thread,NULL,thread_function,NULL)){ ???????perror("Thread creation failed!"); ???????exit(1); ???} ? ???while(print_count1++ < 5){ ???????/*主線程:如果run_now為1就把它修改為2*/ ???????if(run_now == 1) { ???????????printf("main thread is run\n"); ???????????run_now = 2; ???????} else { ???????????printf("main thread is sleep\n"); ???????????sleep(1); ???????} ???} ????????//等待子線程結束 ???pthread_join(a_thread,NULL); ???exit(0); } ? void *thread_function(void *arg) { ??int print_count2 = 0; ??while(print_count2++ < 5){ ??????if(run_now == 2) /*子線程:如果run_now為1就把它修改為1*/ ??????{ ??????????printf("function thread is run\n"); ??????????run_now = 1; ??????} ??????else ??????{ ??????????printf("function thread is sleep\n"); ??????????sleep(1); ??????} ??} ??pthread_exit(NULL); } |
運行結果:
現象:main線程和function線程是交替運行的。它們都可以對run_now進行操作。
加鎖后的代碼
| #include <stdio.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> ? void *thread_function(void *arg); int run_now=1;?/*用run_now代表共享資源*/ pthread_mutex_t work_mutex;?/*定義互斥量*/ ? int main(void) { ???int res; ???int print_count1=0; ???pthread_t a_thread; ? ???if(pthread_mutex_init(&work_mutex,NULL)!=0)?/*初始化互斥量*/ ???{ ???????perror("Mutex init faied"); ???????exit(1); ???} ? ???if(pthread_create(&a_thread,NULL,thread_function,NULL)!=0)?/*創建新線程*/ ???{ ???????perror("Thread createion failed"); ???????exit(1); ???} ? ???if(pthread_mutex_lock(&work_mutex)!=0)?/*對互斥量加鎖*/ ???{ ???????perror("Lock failed"); ???????exit(1); ???} else { ???????printf("main lock\n"); ???} ? ???while(print_count1++<5) { ???????if(run_now == 1)?/*主線程:如果run_now為1就把它修改為2*/ ???????{ ???????????printf("main thread is run\n"); ???????????run_now=2; ???????} else { ???????????printf("main thread is sleep\n"); ???????????sleep(1); ???????} ???} ? ???if(pthread_mutex_unlock(&work_mutex)!=0) /*對互斥量解鎖*/ ???{ ???????perror("unlock failed"); ???????exit(1); ???} else { ???????printf("main unlock\n"); ???} ? ???pthread_mutex_destroy(&work_mutex); /*收回互斥量資源*/ ???pthread_join(a_thread,NULL); /*等待子線程結束*/ ???exit(0); } ? void *thread_function(void *arg) { ???int print_count2=0; ???sleep(1); ? ???if(pthread_mutex_lock(&work_mutex)!=0) { ???????perror("Lock failed"); ???????exit(1); ???} else { ???????printf("function lock\n"); ???} ??? ???while(print_count2++<5) { ???????if(run_now==2)?/*分進程:如果run_now為1就把它修改為1*/ ???????{ ???????????printf("function thread is run\n"); ???????????run_now=1; ???????} else { ???????????printf("function thread is sleep\n"); ???????????sleep(1); ???????} ???} ? ???if(pthread_mutex_unlock(&work_mutex)!=0)?/*對互斥量解鎖*/ ???{ ???????perror("unlock failed"); ???????exit(1); ???} else { ???????printf("function unlock\n"); ???} ???pthread_exit(NULL); } |
運行結果如下:
總結:從運行結果可以看到,當主進程把互斥量鎖住后,子進程就不能對共享資源進行操作了,只能是同步的操作了。
| #include<stdio.h> #include<stdlib.h> #include<pthread.h> #define NLOOP 5000 ? int counter; pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; ? void *doit(void *); ? int main(int argc,char **argv){ ???pthread_t tidA,tidB; ? ???pthread_create(&tidA,NULL,doit,NULL); ???pthread_create(&tidB,NULL,doit,NULL); ? ???/*wait for both thread to terminate*/ ???pthread_join(tidA,NULL); ???pthread_join(tidB,NULL); ? ???return 0; } ? void *doit(void *vptr){ ???int i,val; ???for(i = 0;i < NLOOP;i++) { ???????pthread_mutex_lock(&counter_mutex); ???????val = counter; ???????printf("%x:%d\n",(unsigned int) pthread_self(),val + 1); ???????counter = val + 1; ? ???????pthread_mutex_unlock(&counter_mutex); ???} ? ???return NULL; } |
運行結果:
死鎖
A同一個線程在擁有A鎖的情況下再次請求獲得A鎖
B線程一擁有A鎖,請求獲得B鎖;線程二擁有B鎖,請求獲得A鎖,出現死鎖,最終導致的結果是互相等待。
總結
以上是生活随笔為你收集整理的1线程同步:互斥量,死锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华硕笔记本怎么改主板模式吗 如何将华硕笔
- 下一篇: 进入bios以后怎么启动不了怎么回事 进