ACE線程管理機制-併發控制(1)

ACE Lock類屬

鎖類屬包含的類包裝簡單的鎖定機制,比如互斥體、信號量、讀/寫互斥體和令牌等。這裏我就以互斥體爲例簡單的介紹一下其使用方法,對其它的鎖類進行一些簡單的說明。

1.互斥體的使用。

互斥體用於保護共享的易變代碼,也就是全局或靜態數據。這樣的數據必須通過互斥體進行保護,以防止它們在多個線程同時訪問時損壞。

在ACE中可以通過ACE_Thread_Mutex實現線程的訪問互斥,下面的例子演示ACE_Thread_Mutex類的使用。

#include "ace/Thread.h"
#include "ace/Synch.h"

#include <iostream>
using namespace std;


ACE_Thread_Mutex mutex;

void* Thread1(void *arg)
{
    mutex.acquire();
    ACE_OS::sleep(3);
    cout<<endl<<"hello thread1"<<endl;
    mutex.release();

    return NULL;
}

void* Thread2(void *arg)
{
    mutex.acquire();
    cout<<endl<<"hello thread2"<<endl;
    mutex.release();

    return NULL;
}

int main(int argc, char *argv[])
{
    ACE_Thread::spawn((ACE_THR_FUNC)Thread1);
    
    //Thread2 比Thread1晚創建1秒鐘,故後嘗試獲取互斥體
    ACE_OS::sleep(1);
    ACE_Thread::spawn((ACE_THR_FUNC)Thread2);
    
    while(true)
        ACE_OS::sleep(10);

    return 0;
}

ACE_Thread_Mutex主要有兩個方法:

  1. acquire():用來獲取互斥體,如果無法獲取,將阻塞至獲取到爲止。
  2. release():用來釋放互斥體,從而使自己或者其它線程能夠獲取互斥體。

當線程要訪問共享資源時,首先調用acquire()方法獲取互斥體,從而獲取對改互斥體所保護的共享資源的唯一訪問權限,訪問結束時調用釋放互斥體,使得其它線程能獲取共享資源的訪問權限。

在此例中,本來Thread2的打印消息在Thread1之前,但由於Thread1先獲得互斥體,故Thread2只有待Thread1結束後才能進入臨界區。讀者朋友們可以通過將ACE_Thread_Mutex替換爲ACE_NULL_Mutex看一下不加鎖的執行結果。

2.ACE Lock類屬簡介。

ACE Lock類屬列表如下:

名字

描述

ACE_Mutex

封裝互斥機制(根據平臺,可以是mutex_t、pthread_mutex_t等等)的包裝類,用於提供簡單而有效的機制來使對共享資源的訪問序列化。它與二元信號量(binary semaphore)的功能相類似。可被用於線程和進程間的互斥。

ACE_Thread_Mutex

可用於替換ACE_Mutex,專用於線程同步。

ACE_Process_Mutex

可用於替換ACE_Mutex,專用於進程同步。

ACE_NULL_Mutex

提供了ACE_Mutex接口的"無爲"(do-nothing)實現,可在不需要同步時用作替換。

ACE_RW_Mutex

封裝讀者/作者鎖的包裝類。它們是分別爲讀和寫進行獲取的鎖,在沒有作者在寫的時候,多個讀者可以同時進行讀取。

ACE_RW_Thread_Mutex

可用於替換ACE_RW_Mutex,專用於線程同步。

ACE_RW_Process_Mutex

可用於替換ACE_RW_Mutex,專用於進程同步。

ACE_Semaphore

這些類實現計數信號量,在有固定數量的線程可以同時訪問一個資源時很有用。在OS不提供這種同步機制的情況下,可通過互斥體來進行模擬。

ACE_Thread_Semaphore

應被用於替換ACE_Semaphore,專用於線程同步。

ACE_Process_Semaphore

應被用於替換ACE_Semaphore,專用於進程同步。

ACE_Token

提供"遞歸互斥體"(recursive mutex),也就是,當前持有某令牌的線程可以多次重新獲取它,而不會阻塞。而且,當令牌被釋放時,它確保下一個正阻塞並等待此令牌的線程就是下一個被放行的線程。

ACE_Null_Token

令牌接口的"無爲"(do-nothing)實現,在你知道不會出現多個線程時使用。

ACE_Lock

定義鎖定接口的接口類。一個純虛類,如果使用的話,必須承受虛函數調用開銷。

ACE_Lock_Adapter

基於模板的適配器,允許將前面提到的任意一種鎖定機制適配到ACE_Lock接口。

可以簡單的分爲以下幾類:

  1. 互斥鎖
    互斥鎖(通常稱爲"互斥體"或"二元信號量")用於保護多線程控制併發訪問的共享資源的完整性。互斥體通過定義臨界區來序列化多線程控制的執行,在臨界區中每一時刻只有一個線程在執行它的代碼。互斥體簡單而高效(時間和空間)。
    ACE線程庫提供了Mutex式的類(是一組互斥體對象,擁有類似的接口),他是一種簡單而高效的類型是"非遞歸"互斥體。非遞歸互斥體不允許當前擁有互斥體的線程在釋放它之前重新獲取它。否則,將會立即發生死鎖。遞歸互斥體在ACE Recursive_Thread_Mutex類中可移植地實現。
  2. 讀者/作者鎖
    讀者/作者鎖與互斥體相類似。例如,獲取讀者/作者鎖的線程也必須釋放它。多個線程可同時獲取一個讀者/作者鎖用於讀,但只有一個線程可以獲取該鎖用於寫。當互斥體保護的資源用於讀遠比用於寫要頻繁時,讀者/作者互斥體有助於改善併發的執行。
    ACE線程庫提供了一個叫作RW_Mutex的類,在C++封裝類中可移植地實現了讀者/作者鎖的語義。讀者/作者鎖將優先選擇權給作者。因而,如果有多個讀者和一個作者在鎖上等待,作者將會首先獲取它。

計數信號量
在概念上,計數信號量是可以原子地增減的整數。如果線程試圖減少一個值爲零的信號量的值,它就會阻塞,直到另一個線程增加該信號量的值。
計數信號量用於追蹤共享程序狀態的變化。它們記錄某種特定事件的發生。因爲信號量維護狀態,它們允許線程根據該狀態來作決定,即使事件是發生在過去。
信號量比互斥體效率要低,但是,它們要更爲通用,因爲它們無需被最初獲取它們的同一線程獲取和釋放。這使得它們能夠用於異步的執行上下文中(比如信號處理器)。ACE線程庫提供一個叫作Semaphore的類來可移植地在C++包裝類中實現信號量語義。

發佈了9 篇原創文章 · 獲贊 2 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章