使用互斥同步
在多執行緒程式中同步訪問的另乙個方法就是使用互斥,其作用允許程式鎖住乙個物件,從而只有乙個執行緒可以訪問他。要控制對臨界區**的訪問,在我們進入這段**之前鎖住乙個互斥量,並且在我們完成操作時進行解鎖。
使用互斥所需要基本函式與訊號量所需要的函式相似,其宣告如下:
#include
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t
*mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
如平常一樣,成功時返回0,如果失敗則會返回乙個錯誤**,但是並沒有設定errno;我們必須使用返回**。
與訊號量相類似,這些函式以乙個指向前面宣告的物件的指標為引數,在互斥方法是乙個pthread_mutex_t。額外的屬性引數pthread_mutexattr_t允許我們為互斥提供屬性,這可以控制其行為。屬性型別預設為"fast"。這有乙個小的缺點,如果我們的程式試著在乙個已經上鎖的互斥量上呼叫pthread_mutex_lock,程式就會阻塞。因為擁有鎖的執行緒現在被阻塞了,互斥量就不會被解鎖,從而程式就會進入死鎖狀態。可以修改互斥量的屬性,從而他或者可以檢測這種情況並返回乙個錯誤,或者是迴圈操作並且在同乙個執行緒上允許多個鎖。
設定互斥量的屬性超出了本書的範圍,所以我們會為屬性指標傳遞null並且使用預設行為。我們可以通過閱讀pthread_mutex_init手冊頁了解修改屬性的內容。
試驗--執行緒互斥
再一次說明,下面的程式是我們原始程式thread1.c的修改版,但是進行了大量的修改。這一次,我們有一些偏狂來訪問我們的臨界變數,並且使用乙個互斥量來保證每次只有乙個執行緒訪問他們。為了使得**更易於閱讀,我們忽略了由互斥量加鎖與解鎖操作返回值的錯誤檢測。在生產**中,我們應該檢測這些返回值。下面是這個新程式,thread4.c:
#include
#include
#include
#include
#include
#include
void *thread_function(void *arg);
pthread_mutex_t work_mutex;
#define work_size 1024
char work_area[work_size];
int time_to_exit = 0;
int main()
res = pthread_create(&a_thread,null,thread_function,null);
if(res != 0)
pthread_mutex_lock(&work_mutex);
printf("input some text, enter 'end' to finish\n");
while(!time_to_exit)
else}}
pthread_mutex_unlock(&work_mutex);
printf("\nwaiting for thread to finish...\n");
res = pthread_join(a_thread,&thread_result);
if(res != 0)
printf("thread joined\n");
pthread_mutex_destroy(&work_mutex);
exit(exit_success);
}void *thread_function(void *arg)
}time_to_exit = 1;
work_area[0] = '\0';
pthread_mutex_unlock(&work_mutex);
pthread_exit(0);
}$ cc -d_reentrant -i/usr/include/nptl thread4.c –o thread4 -l/usr/lib/nptl -
lpthread
$ ./thread4
input some text. enter 『end』 to finish
whit
you input 4 characters
the crow road
you input 13 characters
endwaiting for thread to finish...
thread joined
工作原理
我們開始宣告了乙個互斥量,我們的工作區,而且這次,我們宣告了乙個額外變數:time_to_exit。
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
#define work_size 1024
char work_area[work_size];
int time_to_exit = 0;
然後我們初始化互斥量
res = pthread_mutex_init(&work_mutex, null);
if (res != 0)
接下來我們開始我們的新執行緒。下面是執行緒函式內部執行的**:
pthread_mutex_lock(&work_mutex);
while(strncmp(「end」, work_area, 3) != 0)
}time_to_exit = 1;
work_area[0] = 『\0』;
pthread_mutex_unlock(&work_mutex);
首先,新執行緒嘗試鎖住這個互斥量。如果他已經被鎖住了,呼叫就會阻塞直到互斥量被釋放。一旦我們訪問,我們進行檢測來檢視我們是否正被請求退出。如果我們被請求退出,我們只是簡單的設定time_to_exit,清除工作區的第乙個字元,並且退出。
如果我們不希望退出,我們計算字元數然後清空第乙個字元為空。我們使用將第乙個字元清空的方法來通知讀取程式我們已經完成了計算。我們然後解鎖互斥量並且等待主線程執行。我們會迴圈嘗試鎖住這個互斥量,當我們成功時,我們會檢測主線程是否為我們指定了更多的工作要做。如果沒有,我們解鎖互斥量並等待一段更長的時間。如果有,我們計算字元數並且再次進入迴圈。
下面是主線程:
pthread_mutex_lock(&work_mutex);
printf(「input some text. enter 『end』 to finish\n」);
while(!time_to_exit)
else }}
pthread_mutex_unlock(&work_mutex);
這與上面所說的執行緒類似。我們鎖住工作區域,從而我們可以向其中讀取文字,然後解鎖允許其他的執行緒訪問來計算單詞數。迴圈往復,我們重新鎖住互斥量,檢測單詞數是否進行了計算,如果我們需要等待更長的時間,我們就會釋放這個鎖。正如我們在前面所注意到的,這並不是乙個好的程式設計習慣,而在真實的世界中,我們可以使用訊號量來避免這種情況。然而,這裡的**只是作為乙個例子。
POSIX執行緒 (四)
使用互斥同步 在多執行緒程式中同步訪問的另乙個方法就是使用互斥,其作用允許程式鎖住乙個物件,從而只有乙個執行緒可以訪問他。要控制對臨界區 的訪問,在我們進入這段 之前鎖住乙個互斥量,並且在我們完成操作時進行解鎖。使用互斥所需要基本函式與訊號量所需要的函式相似,其宣告如下 include int pt...
posix 執行緒排程
thread 排程 posix 定義一種優先順序排程模型,此模型確定任何兩個執行緒相對於對方的重要程度。每當有乙個以上的執行緒可以執行 執行就緒 時,系統都將選擇具有最高優先順序的執行緒。posix 執行緒排程語義是按照一種概念模型定義的,在此概念模型中有乙個有效優先順序範圍,並且有一組執行緒列表,...
POSIX執行緒(一)
第12章 posix執行緒 在第11章,我們看到在linux中程序是如何被處理的。這些多程序的特性很久以來就是類unix作業系統的特性。有時使用fork建立乙個新程序的代價實在是太大了。在這種情況下,使得乙個程式同時做兩件事情,或者至少看起來是如此是十分有用的。相對應的,我們也許希望以同樣的方式同時...