當多個控制線程共享相同的內存時,需要確保每個線程看到一致的數據視圖。原因在于,當多個線程同時讀取和修改變量時,會造成共享變量的不一致,因此需要對線程進行同步,確保他們在訪問變量的存儲內容時不會訪問到無效的值。
可以使用pthread的互斥接口來保護數據,確保同一時間只有一個線程訪問數據。互斥量(mutex)本質上是一把鎖,在訪問共享資源前對互斥量進行設置(加鎖),在訪問結束后釋放(解鎖)互斥量。對互斥量加鎖以后,任何其他試圖再次對互斥量加鎖的線程都會被堵塞,直到當前線程釋放該互斥鎖。如果釋放互斥量時有一個以上的線程阻塞,那么所有的該鎖上的阻塞線程都會變成可運行狀態,第一個變為運行的線程可以對互斥量加鎖,其他線程就會看到互斥量是鎖著的,只能再次阻塞直到互斥量變為可用。這種方式下,每次只有一個線程可以執行。 只有將所有線程都設計成遵守相同數據訪問規則的,互斥機制才能正常工作。操作系統并不為我們做數據訪問的串行化。如果允許某個線程在沒有得到鎖的情況下也可以訪問共享資源,那么即使其他的線程在使用共享資源前都申請鎖,也還是會出現數據不一致的問題。 互斥變量是用pthread_mutex_t數據類型表示。在使用互斥變量以前,必須首先對它進行初始化,可以把它設置為常量PTHREAD_MUTEX_INITIALIZER(只適用于靜態分配的互斥量),也可以調用pthread_mutex_init函數進行初始化。如果動態分配互斥量(例如,通過調用malloc函數),在釋放內存前需要調用pthread_mutex_destory。
#include <pthread.h>pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);int pthread_mutex_destroy(pthread_mutex_t *mutex);-------------------------------------------------pthread_mutex_init always returns 0. The other mutex functions return 0 on success and a non-zero error code on error.pthread_mutex_trylock嘗試對互斥量加鎖,成功返回0,否則不能加互斥鎖,返回EBUSY。
#include <stdio.h>#include <stdlib.h>#include <pthread.h>typedef struct foo{ int f_count; pthread_mutex_t f_lock; int f_id; /* ... more stuff here ...*/} foo;/* allocate the object */foo*foo_alloc(int id) { foo *fp; if((fp = malloc(sizeof(foo))) != NULL) { fp->f_count = 1; fp->f_id = id; if(pthread_mutex_init(&fp->f_lock, NULL) != 0) { free(fp); return NULL; } } return fp;}/* add a reference to the object */voidfoo_hold(foo *fp){ pthread_mutex_lock(&fp->f_lock); fp->f_count ++; pthread_mutex_unlock(&fp->f_lock);}/* release a reference tp the object */voidfoo_rele(foo *fp){ pthread_mutex_lock(&fp->f_lock); if(--fp->f_count == 0) { pthread_mutex_unlock(&fp->f_lock); pthread_mutex_destroy(&fp->f_lock); } else { pthread_mutex_unlock(&fp->f_lock); }}線程退出時并不會釋放當前持有且未釋放的mutex鎖,因此當其他線程在申請此鎖時會被阻塞;只有當線程所在的進程退出時,mutex鎖才會被操作系統釋放。
// Example:zhuqingping@Ubuntu:~/Study/C/pthread$ cat thread_exit_without_release_lock.c #include <pthread.h>#include <stdio.h>#include <stdlib.h>pthread_mutex_t fastmutex;void *my_new_thread(void *args){新聞熱點
疑難解答