Linux下關於互斥鎖及同步的移植(二)

2021-09-21 23:12:37 字數 4321 閱讀 5595

在 windows 中,事件物件是那些需要使用setevent()函式顯式地將其狀態設定為有訊號狀態的同步物件。事件物件**有兩種型別:

事件物件有兩種狀態,有訊號(signaled)狀態 和 無訊號(non-signaled)狀態。對事件物件呼叫的等待函式會阻塞呼叫執行緒,直到其狀態被設定為有訊號狀態為止。

在進行平台的遷移時,需要考慮以下問題:

還有幾點非常重要,需要說明一下:

建立/開啟事件物件

在 windows 中,我們使用createevent()來建立事件物件。

handle createevent(

lpsecurity_attributes lpeventattributes,

bool bmanualreset,

bool binitialstate,

lpctstr lpname

)

在這段**中:

這個函式建立乙個手工重置或自動重置的事件物件,同時還要設定改物件的初始狀態。這個函式返回事件物件的控制代碼,這樣就可以在後續的呼叫中使用這個事件物件了。

openevent()用來開啟乙個現有的有名事件物件。這個函式返回該事件物件的控制代碼。

handle openevent(

dword dwdesiredaccess,

bool binherithandle,

lpctstr lpname

)

在這段**中:

在 linux 中,可以呼叫sem_init()來建立乙個 posix 訊號量:int sem_init(sem_t *sem, int pshared, unsigned int value)(其中value(即訊號量計數值)被設定為這個訊號量的初始狀態)。

linux pthreads 使用pthread_cond_init()來建立乙個條件變數:int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)

可以使用pthread_cond_initializer常量靜態地對pthread_cond_t型別的條件變數進行初始化,也可以使用pthread_condattr_init()對其進行初始化,這個函式會對與這個條件變數關聯在一起的屬性進行初始化。可以呼叫pthread_condattr_destroy()用來銷毀屬性:

int pthread_condattr_init(pthread_condattr_t *attr)

int pthread_condattr_destroy(pthread_condattr_t *attr)

等待某個事件

在 windows 中,等待函式提供了獲取同步物件的機制。我們可以使用不同型別的等待函式(此處我們只考慮waitforsingleobject())。這個函式會使用乙個互斥物件的控制代碼,並一直等待,直到它變為有訊號狀態或超時為止。

dword waitforsingleobject(

handle hhandle,

dword dwmilliseconds

);

在這段**中:

linux posix 訊號量使用sem_wait()來掛起呼叫執行緒,直到訊號量的計數器變成非零的值為止。然後它會自動減小訊號量計數器的值:int sem_wait(sem_t * sem)

在 posix 訊號量中並沒有提供超時操作。這可以通過在乙個迴圈中執行非阻塞的sem_trywait()來實現,該函式會對超時時間進行計數:int sem_trywait(sem_t * sem).

linux pthreads 使用pthread_cond_wait()來阻塞呼叫執行緒,其時間是不確定的:int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)。在另外一方面,如果呼叫執行緒需要被阻塞一段確定的時間,那麼就可以使用pthread_cond_timedwait()來阻塞這個執行緒。如果在這段指定的時間內條件變數並沒有出現,那麼pthread_cond_timedwait()就會返回乙個錯誤:int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime)。在這裡,abstime引數指定了乙個絕對時間(具體來說,就是從 1970 年 1 月 1 日 0 時 0 分 0 秒到現在所經過的時間。)

改變事件物件的狀態

函式setevent()用來將事件物件的狀態設定為有訊號狀態。對乙個已經設定為有訊號狀態的事件物件再次執行該函式是無效的。

bool setevent(

handle hevent

)

linux posix 訊號量使用sem_post()來發出乙個事件訊號量。這會喚醒在該訊號量上阻塞的所有執行緒:int sem_post(sem_t * sem)

呼叫pthread_cond_signal()被用在 linuxthreads 中,以喚醒在某個條件變數上等待的乙個執行緒,而pthread_cond_broadcast()用來喚醒在某個條件變數上等待的所有執行緒。

int pthread_cond_signal(pthread_cond_t *cond)

int pthread_cond_broadcast(pthread_cond_t *cond)

注意,條件函式並不是非同步訊號安全的,因此不能在訊號處理函式中呼叫。具體地說,在訊號處理函式中呼叫pthread_cond_signal()pthread_cond_broadcast()可能會導致呼叫執行緒的死鎖。

重置事件的狀態

在 windows 中,resetevent()用來將事件物件的狀態重新設定為無訊號狀態。

bool resetevent(

handle hevent

);

在 linux 中,條件變數和 posix 訊號量都是自動重置型別的。

關閉/銷毀事件物件

在 windows 中,closehandle()用來關閉或銷毀事件物件。

bool closehandle(

handle hobject

);

在這段**中,hobject是指向同步物件控制代碼的指標。

在 linux 中,sem_destroy()/ pthread_cond_destroy()用來銷毀訊號量物件或條件變數,並釋放它們所持有的資源:

int sem_destroy(sem_t *sem)

int pthread_cond_destroy(pthread_cond_t *cond)

有名事件物件

在 linux 中,程序之間有名事件物件所實現的功能可以使用 system v 訊號量實現。system v 訊號量是計數器變數,因此可以實現 windows 中事件物件的功能,訊號量的計數器的初始值可以使用semctl()設定為 0。

要將某個事件的狀態修改為有訊號狀態,可以使用semop(),並將sem_op的值設定為 1。要等待某個事件,則可以使用semop()函式,並將sem_op的值設定為 -1,這樣就可以阻塞呼叫程序,直到它變為有訊號狀態為止。

可以通過使用semctl()將訊號量計數器的初始值設定為 0 來獲得訊號量。在使用完共享資源之後,可以使用semop()將訊號量計數設定為 1。關於每個 system v 訊號量的原型,請參閱本文中有關訊號量一節的內容。

Linux 執行緒同步 互斥量(互斥鎖)

1 執行緒同步的目的是不管執行緒之間的執行如何穿插,其執行結果都是正確的。即保證多執行緒執行下結果的確定性。2 同步就是讓所有執行緒按照一定的規則執行,使得其正確性和效率都有跡可循,即執行緒同步就是對執行緒之間的穿插進行控制。3 每個物件都對應於乙個 互斥鎖 的標記,這個標記用來保證在任一時刻,只能...

linux執行緒》同步互斥機制之 互斥鎖

本文基於訊號量 如果訊號量的值最多為1,那實際上相當於乙個共享資源在任意時刻最多只能有乙個執行緒在訪問,這樣的邏輯稱為 互斥 這時,有一種更加方便和語義更加準確的工具來滿足這種邏輯 互斥鎖。幾個執行緒同時去搶乙個鎖,誰搶到了鎖就進門把房間鎖上,訪問資料,出來後之前解鎖。照這樣的邏輯,互斥鎖的操作無非...

Linux多執行緒同步 互斥鎖

當多個執行緒對同乙個資源進行訪問的時候,為了這個資源的安全性,我們需要對這個資源進行鎖定,規定同一時間只有乙個資源能夠獲得該鎖的鑰匙,其它執行緒要獲得該資源需要等待該執行緒 互斥鎖建立 pthread mutex t mutex 互斥鎖初始化 mutex pthread mutex initiali...