對于作業系統而言,在并行程式設計中難免會遇到資料同步和共享的問題,本文針對這個問題,以windows系統為例回顧一下資源同步的相關問題。要點如下:
1.同步和資料共享
資料征用
2.同步原語
1.互斥和臨界區
2.自旋鎖
3.信号量
4.讀寫鎖
5.屏障
6.原子操作與無鎖代碼
3.程序和程序間通信
1.共享記憶體和映射檔案
2.條件變量
3.信号和事件
4.消息隊列
5.命名管道
6.socket網絡棧
知識點:句柄
許多windows API函數都傳回句柄。句柄隻是無符号整數,但卻有特殊的用途。傳回句柄的windows API 調用實際上是在核心空間建立某個資源,句柄隻是這個資源的索引。當應用程式使用完該資源後,就可調用CloseHandle()使核心釋放相關的核心空間資源。
建立線程的3種不同的方式
調用_beginthread()是個吸引人的選擇,這個函數的參數較少,并且線上程退出後清除句柄。但是,如果線程終止,則_beginthread()調用傳回的句柄将是無效的,或是被重用的,是以無法查詢線程的狀态,甚至無法肯定線程句柄是最初指向同一線程的句柄。
加上getchar()的差別
判斷一個數是否為素數:
#include<math.h>
int isprime(int number)
{
int i;
for( i = 2; i < (int) (sqrt((float)number) + 1.0); i++)
if(number % i == 0 ){ return 0;}
}
return 1;
測試給定範圍内數字是否為素數的算法,如果兩個線程同時通路變量counter,這将導緻資料征用,正确的代碼需要對遞增變量counter的操作進行保護。
volatile int counter = 0;
unsigned int __stdcall test(void *)
while(counter < 100)
int number = counter++;
//c++格式話輸出要用cout對象的方法來控制
printf("ThreadID %i value = %i is prime = %i \n", GetCurrentThreadId(), number , isprime(number) );
return 0;
1.保護對臨界區代碼的通路:
// testofCriticalSection.cpp : 定義控制台應用程式的入口點。
//
使線程休眠然後再喚醒線程非常耗時,因為這涉及進入核心。所有臨界區在設計上都應保證耗時盡可能短。要謹記,很可能線程進入休眠時,原處于臨界區的線程已經離開。是以,令等待線程休眠後再喚醒浪費了很多時間。
有兩種選擇解決上述問題:
1.使用TryEnterCriticalSection()避免讓調用線程休眠
2.面向臨界區設定旋轉計數的方法
InitializeCriticalSetionAndSpinCount( &critical,1000)
SetCriticalSectionSpinCount( &critical, 1000)
參考文獻:
戈夫. 多核應用程式設計實戰[M]. 人民郵電出版社, 2013.