天天看點

Windows下多線程資料同步互斥的有關知識



對于作業系統而言,在并行程式設計中難免會遇到資料同步和共享的問題,本文針對這個問題,以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()調用傳回的句柄将是無效的,或是被重用的,是以無法查詢線程的狀态,甚至無法肯定線程句柄是最初指向同一線程的句柄。

Windows下多線程資料同步互斥的有關知識

加上getchar()的差別

Windows下多線程資料同步互斥的有關知識

判斷一個數是否為素數:

#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 : 定義控制台應用程式的入口點。

//

Windows下多線程資料同步互斥的有關知識

使線程休眠然後再喚醒線程非常耗時,因為這涉及進入核心。所有臨界區在設計上都應保證耗時盡可能短。要謹記,很可能線程進入休眠時,原處于臨界區的線程已經離開。是以,令等待線程休眠後再喚醒浪費了很多時間。

有兩種選擇解決上述問題:

1.使用TryEnterCriticalSection()避免讓調用線程休眠

2.面向臨界區設定旋轉計數的方法

InitializeCriticalSetionAndSpinCount( &critical,1000)

SetCriticalSectionSpinCount( &critical, 1000)

參考文獻:

戈夫. 多核應用程式設計實戰[M]. 人民郵電出版社, 2013.