1. 程式人生 > >【VS2010】C++多執行緒同步與互斥簡單運用

【VS2010】C++多執行緒同步與互斥簡單運用

繼以往的想法,寫這點文字,貼上點程式碼,是為了增加自己的記憶,也希望能幫助到需要幫助的人。

1.  互斥量,Mutex

#include <Windows.h>

#include <iostream>

usingnamespace std;  

DWORD WINAPI Thread1(LPVOID lpParmeter);  

DWORD WINAPI Thread2(LPVOID lpParmeter);  

staticHANDLE g_hMutex = INVALID_HANDLE_VALUE;  

staticint g_iCnt = 100;  

int main()  

{  

    HANDLE hThread1 = INVALID_HANDLE_VALUE;  

    HANDLE hThread2 = INVALID_HANDLE_VALUE;  

    g_hMutex = CreateMutex(NULL, FALSE, "Mutex");  

    // 第二個引數:建立者是否擁有所有權,FALSE為沒有所有權,

    // 遇到第一個WaitForSingleObject的時候就把所有權給它,

    // 所以Thread1裡面的WaitForSingleObject(g_hMutex, INFINITE)能夠繼續執行

    if (!g_hMutex)  

    {  

        cout << "Failed to CreateMutex !" << endl;  

        return 0;  

    }  

    hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);  

    hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);  

    Sleep(4000);        // 讓2個執行緒有足夠的時間執行完操作。

    CloseHandle(hThread1);  

    CloseHandle(hThread2);  

    system("PAUSE");  

    return 0;  

}  

DWORD WINAPI Thread1(LPVOID lpParmeter)  

{  

    while (true)  

    {  

        // 請求事件物件

        WaitForSingleObject(g_hMutex, INFINITE);    // INFINITE: 長時間等待,差不多50天左右吧!

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "Thread1:" << g_iCnt-- << endl;  

            ReleaseMutex(g_hMutex);                 // 釋放資源

        }  

        else

        {  

            ReleaseMutex(g_hMutex);  

            break;  

        }  

    }  

    return 0;  

}  

DWORD WINAPI Thread2(LPVOID lpParameter)//thread data

{  

    while (true)  

    {  

        // 請求事件物件

        WaitForSingleObject(g_hMutex,INFINITE);  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "thread2:" << g_iCnt-- << endl;  

            ReleaseMutex(g_hMutex);  

        }  

        else

        {  

            ReleaseMutex(g_hMutex);  

            break;  

        }  

    }  

    return 0;  

}  

幾個注意的地方:

(1)互斥量為核心物件,能夠與其他執行緒或特殊事件取得同步;

(2)速度比臨界區要慢;

(3)互斥量物件與所有其它核心物件的不同之處在於它是被執行緒所擁有的,互斥量物件除了記錄當前訊號狀態外,還要記住此時那個執行緒擁有它。

(4)這個常來被運用於限制程式啟動次數!

2.事件 Event

#include <Windows.h>

#include <iostream>

usingnamespace std;  

DWORD WINAPI Thread1(LPVOID lpParmeter);  

DWORD WINAPI Thread2(LPVOID lpParmeter);  

staticHANDLE g_hEvent = INVALID_HANDLE_VALUE;  

staticint g_iCnt = 100;  

int main()  

{  

    HANDLE hThread1 = INVALID_HANDLE_VALUE;  

    HANDLE hThread2 = INVALID_HANDLE_VALUE;  

    g_hEvent = CreateEvent(NULL, falsefalse"Event");  

    if (!g_hEvent)  

    {  

        cout << "Failed to CreateEvent !" << endl;  

        return 0;  

    }  

    /*HANDLE CreateEvent( 

    LPSECURITY_ATTRIBUTES lpEventAttributes,    // SECURITY_ATTRIBUTES結構指標,可為NULL 

    BOOL bManualReset,                          // 手動/自動 

                                                // TRUE: 在WaitForSingleObject後必須手動呼叫ResetEvent清除訊號 

                                                // FALSE:在WaitForSingleObject後,系統自動清除事件訊號 

    BOOL bInitialState,                         // 初始狀態 

    LPCTSTR lpName                              // 事件的名稱 

    );*/

    hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);  

    hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);  

    SetEvent(g_hEvent);  

    Sleep(4000);        // 讓2個執行緒有足夠的時間執行完操作。

    CloseHandle(hThread1);  

    CloseHandle(hThread2);  

    system("PAUSE");  

    return 0;  

}  

DWORD WINAPI Thread1(LPVOID lpParmeter)  

{  

    while (true)  

    {  

        // 請求事件物件

        WaitForSingleObject(g_hEvent, INFINITE);    // INFINITE: 長時間等待,差不多50天左右吧!

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "Thread1:" << g_iCnt-- << endl;  

            SetEvent(g_hEvent);  

        }  

        else

        {  

            SetEvent(g_hEvent);  

            break;  

        }  

    }  

    return 0;  

}  

DWORD WINAPI Thread2(LPVOID lpParameter)//thread data

{  

    while (true)  

    {  

        // 請求事件物件

        WaitForSingleObject(g_hEvent,INFINITE);  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "thread2:" << g_iCnt-- << endl;  

            SetEvent(g_hEvent);  

        }  

        else

        {  

            SetEvent(g_hEvent);  

            break;  

        }  

    }  

    return 0;  

}  

幾個注意的地方:

(1).和Mutex使用差不多,只有細微的差別;

(2).可以使用SetEvent或ResetEvent改變其狀態;

(3).在應用程式中任意一處沒有正確的按照規則呼叫SetEvent或ResetEvent,將達不到同步或互斥的目的;

(4).一般來說,都是利用Event來進行同步,而不是我們這裡的讓它來達到互斥;

(5).Event處於無訊號狀態時,相關執行緒或程序退出,系統並不會嘗試將其置為有訊號狀態;

3.臨界區 CRITICAL_SECTION

#include <Windows.h>  

#include <iostream>  

using namespace std;  

DWORD WINAPI Thread1(LPVOID lpParmeter);  

DWORD WINAPI Thread2(LPVOID lpParmeter);  

CRITICAL_SECTION g_CriticalSection; // 定義  

static int g_iCnt = 100;  

int main()  

{  

    HANDLE hThread1 = INVALID_HANDLE_VALUE;  

    HANDLE hThread2 = INVALID_HANDLE_VALUE;  

    InitializeCriticalSection(&g_CriticalSection);      // 初始化  

    hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);  

    hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);  

    Sleep(4000);        // 讓2個執行緒有足夠的時間執行完操作。  

    CloseHandle(hThread1);  

    CloseHandle(hThread2);  

    DeleteCriticalSection(&g_CriticalSection);          // 刪除  

    system("PAUSE");  

    return 0;  

}  

DWORD WINAPI Thread1(LPVOID lpParmeter)  

{  

    while (true)  

    {  

        EnterCriticalSection(&g_CriticalSection);       // 進入臨界區,獲得所有權,其他執行緒就等待  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "Thread1:" << g_iCnt-- << endl;  

            LeaveCriticalSection(&g_CriticalSection);   // 離開臨界區,釋放所有權  

        }  

        else  

        {  

            LeaveCriticalSection(&g_CriticalSection);  

            break;  

        }  

    }  

    return 0;  

}  

DWORD WINAPI Thread2(LPVOID lpParameter)//thread data  

{  

    while (true)  

    {  

        EnterCriticalSection(&g_CriticalSection);  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "thread2:" << g_iCnt-- << endl;  

            LeaveCriticalSection(&g_CriticalSection);  

        }  

        else  

        {  

            LeaveCriticalSection(&g_CriticalSection);  

            break;  

        }  

    }  

    return 0;  

}  

幾個注意的地方:

(1).比Mutex速度快;

(2).臨界區線上程內的分配必須是全域性的;

(3). 臨界區一次只允許一個執行緒訪問;

4.訊號量Semaphore

    首先說說那些關於訊號量那些不得不讓人傷心的事情,因為筆者大學不好學習,非常調皮,而訊號量又是老師最討論及考試的話題之一,所以我覺得這個東西非常扯淡,非常影響情緒,於是放在最後。------以上是為題外話。

    為什麼大學老師總是喜歡訊號量呢?

    因為這是一個生產者-消費者模型,並且很多計算機問題都可以看做是生產者-消費者的問題,是同步最易理解的模型。

    關於理論上的知識,我就不說了,書裡面很多的。

    還有我不是很想實現生產者-消費者的模型,就用其他例子代替了。這個有點不負責任。

#include <Windows.h>  

#include <iostream>  

#include <vector>  

using namespace std;  

DWORD WINAPI Thread1(LPVOID lpParmeter);  

DWORD WINAPI Thread2(LPVOID lpParmeter);  

static HANDLE g_hSemaphore = INVALID_HANDLE_VALUE;; // 定義  

static int g_iCnt = 100;  

int main()  

{  

    HANDLE hThread1 = INVALID_HANDLE_VALUE;  

    HANDLE hThread2 = INVALID_HANDLE_VALUE;  

    // HANDLE CreateSemaphore (  

    //  PSECURITY_ATTRIBUTE psa,  

    //  LONG lInitialCount, //開始時可供使用的資源數  

    //  LONG lMaximumCount, //最大資源數  

    //  PCTSTR pszName);  

    g_hSemaphore = CreateSemaphore(NULL, 1, 1, "Semaphore");          

    // 初始化有1個訊號量。  

    if (g_hSemaphore == INVALID_HANDLE_VALUE)  

    {  

        cout << "Failed to Create Semaphore!" << endl;  

        return 0;  

    }  

    hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);  

    hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);  

    Sleep(4000);        // 讓2個執行緒有足夠的時間執行完操作。  

    CloseHandle(hThread1);  

    CloseHandle(hThread2);  

    system("PAUSE");  

    return 0;  

}  

DWORD WINAPI Thread1(LPVOID lpParmeter)  

{  

    while (true)  

    {  

        WaitForSingleObject(g_hSemaphore, INFINITE);        // 釋放一個訊號量  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "Thread1:" << g_iCnt-- << endl;  

            ReleaseSemaphore(g_hSemaphore, 1, NULL);        // 增加一個訊號量  

        }  

        else  

        {  

            break;  

        }  

    }  

    return 0;  

}  

DWORD WINAPI Thread2(LPVOID lpParameter)//thread data  

{  

    while (true)  

    {  

        WaitForSingleObject(g_hSemaphore, INFINITE);  

        if (g_iCnt > 0)  

        {  

            Sleep(20);  

            cout << "thread2:" << g_iCnt-- << endl;  

            ReleaseSemaphore(g_hSemaphore, 1, NULL);  

        }  

        else  

        {  

            break;  

        }  

    }  

    return 0;  

}  

幾個注意的地方:

訊號量核心物件對執行緒的同步方式與前面幾種不同,它允許多個執行緒在同一時刻訪問某一資源,但是需要限制同一時刻訪問此資源的最大執行緒數目。

總結: 執行緒規模 = CPU  * 2 + 1


相關推薦

VS2010C++執行同步互斥簡單運用

繼以往的想法,寫這點文字,貼上點程式碼,是為了增加自己的記憶,也希望能幫助到需要幫助的人。 1.  互斥量,Mutex #include <Windows.h> #include <iostream> usingnamespace

Java執行-同步集合和併發集合

同步集合可以簡單地理解為通過synchronized來實現同步的集合。如果有多個執行緒呼叫同步集合的方法,它們將會序列執行。 arrayList和vector、stack Vector是執行緒安全的,原始碼中有很多的synchronized可以看出,而

執行同步互斥

多執行緒執行緒基礎操作 關於本篇部落格的更多程式碼:GitHub連結 執行緒的同步與互斥,學習生產者消費者模型及應用場景 執行緒安全:生產者與消費者模型,讀寫者模型,同步與互斥的實現,互斥鎖,條件變數,posix訊號量,讀寫鎖,自旋鎖 大部分情況,執行緒使用的資料都是區域性變

執行同步互斥(3)

在進行多執行緒程式設計時,難免還要碰到兩個問題,那就執行緒間的互斥與同步: 執行緒同步是指執行緒之間所具有的一種制約關係,一個執行緒的執行依賴另一個執行緒的訊息,當它沒有得到另一個執行緒的訊息時應等待,直到訊息到達時才被喚醒。 執行緒互斥是指對於共享的程序系統資源,在各單個執行緒訪問時的排它性。當有若干個執行

Linux 執行同步互斥

1.同步 同一個程序中的多個執行緒共享所在程序的記憶體資源,當多個執行緒在同一時刻同時訪問同一種共享資源時,需要相互協調,以避免出現數據的不一致和覆蓋等問題,執行緒之間的協調和通訊的就叫做執行緒的同步問題, 執行緒同步的思路: 讓多個執行緒依次訪問共享資源,而不是並行 我

C#執行同步(一)計數器

羅馬人凱撒大帝,威震歐亞非三大陸,臨終告訴侍者說:“請把我的雙手放在棺材外面,讓世人看看,偉大如我凱撒者,死後也是兩手空空。 ICounter.cs類: interface ICounter

C++執行同步技巧(二) ---事件

簡介 Windows線上程控制方面提供了多種訊號處理機制,其中一種便是使用 CreateEvent() 函式建立事件,然後使用訊號控制執行緒執行。其中將事件變為有訊號可使用 SetEvent() 函式,將事件訊號復位(變為無訊號)可使用 ResetEvent(

JavaJava執行實現的聊天客戶端和伺服器

主要涉及知識 ·Java中GUI程式的編寫,包括事件監聽機制。 ·Java的網路通訊程式設計,ServerSocket,Socket類的使用。 ·Java中多執行緒的程式設計,Thread類,Runnable介面的使用。 原始碼 客戶端 package project1

專欄 - Java 執行程式設計

Java 多執行緒程式設計 Java多執行緒程式設計,是併發程式設計的一種(另一種重要的併發程式設計是多程序程式設計)。我們寫java程式一般是執行在同一個程序中的,所以可以簡單的認為:併發程式設計 = 多執行緒程式設計,讓寫作業

ODPSTableTunnel執行下載事例

本篇介紹多執行緒下載 1.多執行緒下載類: package bysql; import java.io.BufferedWriter; import java.io.IOException; import java.util.Date; import java.uti

C++執行同步之Mutex(互斥量)

一、互斥量Mutex同步多執行緒 1、Win32平臺 相關函式和標頭檔案 #include <windows.h> HANDLE CreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes

C++執行同步效率對比之臨界區和原子鎖

多執行緒程式設計經常遇到資料同步問題,通常的做法就是加鎖,之前個人常用臨界區(CTITICAL_SECTION),最近開發高效率程式,尋求更高效的同步方式,才有了對原子鎖的研究。經測試,原子鎖效率確實比臨界區高,用資料衡量,原子鎖的效率是臨界區的5倍左右。 測試方法: 1、

vs2010 mfc c++ 執行

(比較推薦使用該方式在MFC下開發) 有關建立執行緒的問題有三種方法: 1.C語言函式,呼叫_beginthread(); 2.API函式,呼叫CreateThread(); 3.MFC函式,呼叫AfxBeginThread(); 推薦使用MFC函式AfxBeginTh

自用java執行程式設計學習筆記(程式碼片段來源於網路)

執行緒的基本概念 執行緒是在邏輯上等同於作業系統中說的程序,是程序的細分。比如我們使用同一個軟體同時對電腦進行體檢和防毒的時候,我們就是開啟了那個軟體的程序的兩個執行緒,在邏輯上這兩個執行緒是同時被cpu執行的。 執行緒的生命週期 執行緒的生命週期分為建立,就緒,執行,

C++執行同步技術(MFC)

1. 何時使用同步類     MFC 提供的多執行緒類分為兩類:同步物件(CSyncObject、CSemaphore、CMutex、CCriticalSection 和 CEvent)和同步訪問物件(CMultiLock 和 CSingleLock)。 當必須控制對資源的

C#執行同步的幾種方法

9.ReaderWriterLockSlim 類 讀寫鎖的概念很簡單,允許多個執行緒同時獲取讀鎖,但同一時間只允許一個執行緒獲得寫鎖,因此也稱作共享-獨佔鎖。在C#中,推薦使用ReaderWriterLockSlim類來完成讀寫鎖的功能。某些場合下,對一個物件的讀取次數遠遠大於修改次數,如果只是簡單的用lo

Java執行-CyclicBarrier 柵欄

CyclicBarrier 類介紹 CyclicBarrier是一個同步工具類,它允許一組執行緒在到達某個柵欄點(common barrier point)互相等待,發生阻塞,直到最後一個執行緒到達柵欄點,柵欄才會開啟,處於阻塞狀態的執行緒恢復繼續執行.它

[C#學習筆記之執行2]執行同步併發訪問共享資源工具—Lock、Monitor、Mutex、Semaphore

“執行緒同步”的含義         當一個程序啟動了多個執行緒時,如果需要控制這些執行緒的推進順序(比如A執行緒必須等待B和C執行緒執行完畢之後才能繼續執行),則稱這些執行緒需要進行“執行緒同步(thread synchronization)”。         執行緒

C++執行同步之Semaphore(訊號量)

一、執行緒間同步的幾種方式 從上篇博文中可以發現,當多個執行緒對同一資源進行使用時,會產生“爭奪”的情況,為了避免這種情況的產生,也就出現了執行緒間的同步這個技術。執行緒間的同步有多種方式,在接下來的博文中我會依次介紹幾種主流的同步方式,以及他們之間的區別。在

執行中Wait和Join的理解

對於,wait方法的解釋,有時候覺得很矛盾。呼叫某個物件的wait時,需要獲得該物件的鎖,在執行的時候又需要釋放該物件的所有鎖。這是問題一。 另外,在看Join的原始碼,會發現它利用了Wait來實現,但是它的實現原理是怎樣的呢? 這是問題二。 看下原始碼的英文描述: