Linux 線程編程2.0——線程同步-互斥鎖
當我們需要控制對共享資源的存取的時候,可以用一種簡單的加鎖的方法來控制。我們可以創建一個讀/寫程序,它們共用一個共享緩沖區,使用互斥鎖來控制對緩沖區的存取。
函數 pthread_mutex_init()用來生成一個互斥鎖。其函數原型如下:
#include<pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
第一個參數是互斥變量的地址,第二個參數設置互斥變量的屬性,大多數情況下.選擇默認屬性,則傳入空指針
Pthread_mutex_lock()函數聲明開始用互斥鎖上鎖,此後的代碼直至調用 pthread_mutex_ unlock()為止,均被上鎖,即同一時間只能被一個線程調用執行。當一個線程執行到 pthread_mutex_lock()處時,如果該鎖此時被另一個線程使用,那麽此線程被阻塞,線程一直阻塞知道另一個線程釋放此互斥鎖。這兩個函數原型是:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
兩個函數的參數都是互斥變量的地址。函數執行成功返回
互斥鎖使用很方便,但是有一個缺點是使用互斥鎖的過程中很有可能會出現死鎖:兩個線程試圖同時占有兩個資源,並按不同的次序鎖定相應的互斥鎖,例如兩個線程都需要鎖定互斥鎖 l 和互斥鎖 2,A 線程鎖定了互斥鎖 l,B 線程了鎖定互斥鎖 2,此時如果 A 線程在解除互斥鎖 l 之前又去鎖定互斥鎖 2,而 B 恰好又需要去鎖定互斥鎖 l,這時就出現了死鎖。看起來像是繞口令,通俗一點的來解釋:線程 A 和線程 B 都需要獨占使用 2 個資源,但是他們都分別先占據了一個資源,然後有相互等待另外一個資源的釋放,這樣的形成了一個死鎖。此時我們可以使用函數 pthread_mutex_trylock(),它是函數
int pthread_mutex _trylock( pthread_mutex_t*mutex);
當互斥鎖不再使用的時候,應當釋放互斥變量,函數 pthread _mutex.destory()用來釋放一個互斥變量。
代碼:
#include <stdio.h> #include <pthread.h> #include <unistd.h> char buffer[128]; int buffer_has_data=0; pthread_mutex_t mutex; void write_buffer (char *data) { /* 鎖定互斥鎖*/ pthread_mutex_lock (&mutex); if (buffer_has_data == 0) { sprintf( buffer, "%s", data); buffer_has_data=1; } /* 打開互斥鎖*/ pthread_mutex_unlock(&mutex); } void read_buffer(void) { while(1){ /* 鎖定互斥鎖*/ pthread_mutex_lock(&mutex); if(buffer_has_data == 1) { printf("Read buffer, data = [%s]\n", buffer); buffer_has_data=0; } /* 打開互斥鎖*/ pthread_mutex_unlock(&mutex); sleep(1); } } int main ( int argc, char **argv ) { char input[128]; pthread_t reader; /* 用默認屬性初始化一個互斥鎖對象*/ pthread_mutex_init( &mutex, NULL ); pthread_create(&reader, NULL, (void *)(read_buffer), NULL); while( 1 ) { scanf( "%s", input ); write_buffer( input ); } return 0; }
Linux 線程編程2.0——線程同步-互斥鎖