Linux 進程與線程四(加鎖--解鎖)
線程共享進程的內存空間,打開的文件描述符,全局變量。 當有多個線程同事訪問一塊內存空間或者一個變量、一個文件描述符,如果不加控制,那么可能會出現意想不到的結果。
原子操作 對於我們的高級語言(C語言,java,c#),普通的一句代碼一般都是由多條匯編語句組成,計算機CPU每次所執行的都是一條匯編指令 ,一條匯編指令是無法再次拆分的,所以計算機CPU同一時間只能執行一條匯編指令就是一個原子操作。
互斥(mutex)是相互排斥的意思,它是一種鎖或者信號燈。 互斥用來保護多個線程共享的數據和結構不會被同事修改,一個互斥鎖只能有兩個狀態 --locked 加鎖 --unlocked 解鎖 加鎖后互斥不讓其他線程訪問。 任何時刻只能有一個線程來掌握某個互斥上鎖。 鎖操作是一個原子操作 一個線程如果試圖在一個已經加鎖的互斥上再加鎖,這個線程會被掛起,,直到加鎖的線程釋放掉互斥鎖為止。 強調:加鎖解鎖針對的是pthread_mutex_t類型的變量,只要有一個地方加鎖,哪怕在別的線程中有加鎖代碼,那個線程也會被掛起,
只有當pthread_mutex_t類型的變量解鎖后,其他的線程才可以繼續對pthread_mutex_t類型的變量加鎖。 注意:互斥情況下,如果將某個正在加鎖占用資源的進程用pthread_cancel函數取消掉,可能產生死鎖。
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
PTHREAD_MUTEX_INITIALIZER是初始化一個快速鎖的宏定義。
pthread_mutex_lock用戶給mutex加鎖。
pthread_mutex_unlock用於給mutex解鎖
//線程加鎖--pthread_mutex_lock #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <pthread.h> //定義一個全局的互斥變量 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int count = 0; void * MyFunc(void * arg) { if (arg == NULL) { printf("param is not allow NULL!\n"); return NULL; } //加鎖--所有線程都能訪問的全局變量加鎖 pthread_mutex_lock(&mutex); int * pnumx = (int *) arg; int i = 0; while (i < 10) { printf("thread%d count=%d\n", *pnumx, count++); sleep(1); i++; } //解鎖 pthread_mutex_unlock(&mutex); return NULL; } void * MyFunc2(void * arg) { if (arg == NULL) { printf("param is not allow NULL!\n"); return NULL; } //這個鎖和myfunc中的鎖是同一個鎖,myfunc被鎖,這里也會被鎖 pthread_mutex_lock(&mutex); int * pnumx = (int *) arg; int i = 0; while (i < 10) { printf("thread%d count=%d\n", *pnumx, count++); sleep(1); i++; } //解鎖 pthread_mutex_unlock(&mutex); return NULL; } int main(int arg, char * args[]) { pthread_t thr1, thr2; pthread_attr_t attr; pthread_attr_init(&attr); //設置進程為可分離狀態 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); int a = 1, b = 2; //創建線程 if (pthread_create(&thr1, &attr, MyFunc, &a) != 0) { printf("create thread is failed ! error message :%s\n", strerror(errno)); return -1; } //釋放進程屬性對象 pthread_attr_destroy(&attr); if (pthread_create(&thr2, NULL, MyFunc, &b) != 0) { printf("create thread is failed ! error message :%s\n", strerror(errno)); return -1; } pthread_join(thr2, NULL); printf("main end\n"); return 0; }