小心pthread_cond_signal和SetEvent之間的差異

ZZ FROM:?http://blog.csdn.net/absurd/article/details/1402433

=====================================================

轉載時請注明出處和作者聯系方式:http://blog.csdn.net/absurd

作者聯系方式:Li XianJing <xianjimli at hotmail dot com>

更新時間:2006-12-19

=====================================================


今天幫同事查一個多線程的BUG,其中一個線程掛在g_cond_wait上不動了。從代碼來看,看出不出任何問題,g_cond_waitg_cond_signal是嚴格配對的。折騰了兩個小時后,從LOG信息中發現,g_cond_waitg_cond_signal的順序有點問題,一個線程先調g_cond_signal,另外一個線程才調g_cond_wait

?

g_cond_signalglib的封裝,在Linux下,是用pthread_cond_signal模擬的,在Win32下,是用SetEvent模擬的。在Win32下,SetEventWaitForSingleObject在兩個線程中的調用順序沒有關系,奇怪,難道在linux下兩者的調用順序有影響嗎?

?

看了pthread的代碼,果然如此:pthread_cond_signal發現沒有其它線程等待,它直接返回了(見用紅色高亮的代碼)

int?pthread_cond_signal(pthread_cond_t *cond)

{

????if?(cond?==?NULL)

????????return?pth_error(EINVAL,?EINVAL);

????if?(*cond?== PTHREAD_COND_INITIALIZER)

????????if?(pthread_cond_init(cond,?NULL) != OK)

????????????return?errno;

????if?(!pth_cond_notify((pth_cond_t *)(*cond),?FALSE))

????????return?errno;

????return?OK;

}

int?pth_cond_notify(pth_cond_t *cond,?int?broadcast)

{??????

????/* consistency checks */

????if?(cond?==?NULL)

????????return?pth_error(FALSE,?EINVAL);

????if?(!(cond->cn_state & PTH_COND_INITIALIZED))

????????return?pth_error(FALSE,?EDEADLK);

???

????/* do something only if there is at least one waiters (POSIX semantics) */

????if (cond->cn_waiters > 0) {

????????/* signal the condition */

????????cond->cn_state |= PTH_COND_SIGNALED;

????????if?(broadcast)

????????????cond->cn_state |= PTH_COND_BROADCAST;

????????else

????????????cond->cn_state &= ~(PTH_COND_BROADCAST);

????????cond->cn_state &= ~(PTH_COND_HANDLED);

???

????????/* and give other threads a chance to awake */

????????pth_yield(NULL);

????}

?

????/* return to caller */

????return?TRUE;

}

?

晚上回家后,我又看了reactos關于SetEvent的實現。結果也意料之中:沒有線程等待這個Event時,它仍然會設置SignalState(見用紅色高亮的代碼)

LONG

STDCALL

KeSetEvent(PKEVENT?Event,

???????????KPRIORITY?Increment,

???????????BOOLEAN?Wait)

{

????KIRQL?OldIrql;

????LONG?PreviousState;

????PKWAIT_BLOCK?WaitBlock;

?

????DPRINT("KeSetEvent(Event %x, Wait %x)/n",Event,Wait);

?

????/* Lock the Dispathcer Database */

????OldIrql?= KeAcquireDispatcherDatabaseLock();

?

????/* Save the Previous State */

????PreviousState?=?Event->Header.SignalState;

?

????/* Check if we have stuff in the Wait Queue */

????if (IsListEmpty(&Event->Header.WaitListHead)) {

?

????????/* Set the Event to Signaled */

????????DPRINT("Empty Wait Queue, Signal the Event/n");

????????Event->Header.SignalState = 1;

????} else {

?

????????/* Get the Wait Block */

????????WaitBlock?=?CONTAINING_RECORD(Event->Header.WaitListHead.Flink,

??????????????????????????????????????KWAIT_BLOCK,

??????????????????????????????????????WaitListEntry);

?

?

????????/* Check the type of event */

????????if?(Event->Header.Type?== NotificationEvent ||?WaitBlock->WaitType == WaitAll) {

?

????????????if?(PreviousState?== 0) {

?

????????????????/* We must do a full wait satisfaction */

????????????????DPRINT("Notification Event or WaitAll, Wait on the Event and Signal/n");

????????????????Event->Header.SignalState = 1;

????????????????KiWaitTest(&Event->Header,?Increment);

????????????}

?

????????}?else?{

?

????????????/* We can satisfy wait simply by waking the thread, since our signal state is 0 now */

????????????DPRINT("WaitAny or Sync Event, just unwait the thread/n");

????????????KiAbortWaitThread(WaitBlock->Thread,?WaitBlock->WaitKey,?Increment);

????????}

????}

?

????/* Check what wait state was requested */

????if?(Wait?==?FALSE) {

?

????????/* Wait not requested, release Dispatcher Database and return */

????????KeReleaseDispatcherDatabaseLock(OldIrql);

?

????}?else?{

?

????????/* Return Locked and with a Wait */

????????KTHREAD *Thread?= KeGetCurrentThread();

????????Thread->WaitNext =?TRUE;

????????Thread->WaitIrql =?OldIrql;

????}

?

????/* Return the previous State */

????DPRINT("Done: %d/n",?PreviousState);

????return?PreviousState;

}

?

?

而在KeWaitForSingleObject中,它發現SignalState大于0,就會Wait成功(見用紅色高亮的代碼)

NTSTATUS

STDCALL

KeWaitForSingleObject(PVOID?Object,

??????????????????????KWAIT_REASON?WaitReason,

??????????????????????KPROCESSOR_MODE?WaitMode,

??????????????????????BOOLEAN?Alertable,

??????????????????????PLARGE_INTEGER?Timeout)

{

?????????...

if (CurrentObject->Header.SignalState > 0)

????????{

????????????/* Another satisfied object */

????????????KiSatisfyNonMutantWait(CurrentObject, CurrentThread);

????????????WaitStatus = STATUS_WAIT_0;

????????????goto DontWait;

????????}

...

}

?

由此可見,glib封裝的g_cond_signal/g_cond_waitWin32下和Linux下行為并不完全一致。即使不使用glib的封裝,自己封裝或者直接使用時,也要小心這個微妙的陷阱。

?

~~end~~


轉載于:https://www.cnblogs.com/iplus/archive/2012/08/31/4467393.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379364.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379364.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379364.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

eshop.sql(復制的時候注意路徑!!!)

USE [master] GO /****** Object: Database [eshop] Script Date: 2019/11/25 星期一 上午 08:54:14 / CREATE DATABASE [eshop] ON PRIMARY ( NAME N’eshop_dat’, FILENAME N’D:\eshop\eshop_dat.mdf’ , SIZE 10240KB , MAXSIZE 51200KB , FILEGROWTH 5120KB ) LOG O…

doublevalue_Java Double類doubleValue()方法與示例

doublevalueDouble類doubleValue()方法 (Double class doubleValue() method) doubleValue() method is available in java.lang package. doubleValue()方法在java.lang包中可用。 doubleValue() method is used to return the value denoted by this Double object converted…

ffmpeg 命令過濾器裁剪

1 圖片操作&#xff1a; 原圖&#xff1a; 使用ffplay 顯示左半邊 ffplay -i input.png -vf cropiw/2:ih:0:0 可以通過ffmpeg 保存 ffmpeg -i input.png -vf cropiw/2:ih:0:0 out.png 2 視頻操作&#xff1a; 原視頻&#xff1a; 顯示左半邊 ffplay -i cctvhttp.flv -vf …

去除aspx生成的頁面最開始的空行

使用.aspx生成的頁面一般都會有一個或多個空行&#xff0c;當然這些空行不會影響頁面在瀏覽器中的渲染結果&#xff0c;不過在查看源代碼的時候感覺有些別扭&#xff0c;我曾試著去刪除這些空行&#xff0c;但沒有成功&#xff0c;你知道你們有沒有去嘗試。 1 <% Page Langu…

PUBLISH.sql(復制的時候注意路徑!!!)

USE [master] – GO – /****** Object: Database [PUBLISH] Script Date: 2019/11/25 星期一 上午 09:00:04 / – CREATE DATABASE [PUBLISH] ON PRIMARY – ( NAME N’PUBLISH’, FILENAME N’F:\PUBLISH\PUBLISH.mdf’ , SIZE 51200KB , MAXSIZE UNLIMITED, FILEGROWTH …

c ++ 函數的esp指針_在C ++中通過指針訪問成員函數

c 函數的esp指針Create a class along with data member and member functions and then access the member functions by using a pointer in C. 創建一個類以及數據成員和成員函數&#xff0c;然后使用C 中的指針訪問成員函數。 如何通過指針訪問成員函數&#xff1f; (How…

[iphone-cocos2d]分享一段Objective-C可調用的游戲中播放音樂(1)

首先需要引入AudioTool 這個framework 代碼 -(id)initWithPath:(NSString *)path{ UInt32 size, maxPacketSize; char*cookie; inti; if(gThereIsAnActiveTrack) { NSLog("*** WARNING *** GBMusicTrack only plays one track at a time…

匯編語言-010(循環移位ROL,ROR 、進位循環進位RCL,RCR 、有符號數溢出 、雙精度移位SHLD,SHRD、SHL和ADD計算 、位運算應用)

1 &#xff1a;循環移位ROL,ROR,帶進位循環進位RCL,RCR .386 .model flat,stdcall.stack 4096 ExitProcess PROTO,dwExitCode:DWORD.code main PROC;循環左移mov al,40h ;AL 010000000brol al,1 ;AL 100000000b ,CF 0rol al,1 ;AL 000000001b ,CF 1rol al,1 ;A…

[Z]POJ 計算幾何入門題目推薦[轉PKKJ]

http://www.cnblogs.com/eric-blog/archive/2011/05/31/2064785.html http://hi.baidu.com/novosbirsk/blog/item/723a9727a9ab8804918f9dca.html其實也談不上推薦&#xff0c;只是自己做過的題目而已&#xff0c;甚至有的題目尚未AC&#xff0c;讓在掙扎中。之所以推薦計算幾何…

2013年 833c語言程序 江南大學 (A卷)

1.編寫程序實現求兩個整數最大公約數和最小公倍數. 方法一&#xff1a;輾轉相除法 算法思路&#xff1a;兩個整數a,b,其中a>b&#xff0c;求其最大公約數和最小公倍數 步驟① a%bc,其中c為余數 步驟② 若余數c為0&#xff0c;即a可以把b給整除,也就是說這里的b就是其最大公…

二十幾歲失敗的原因

1.缺乏人生目標。在研究過的人們中&#xff0c;9.98%的人沒有"人生目標"&#xff0c;這恐怕是人們失敗的最大原因。  2.自學能力不足。歷史上所謂掌握最高教育的人&#xff0c;幾乎都是"自學型"的。所謂"有教育"的人&#xff0c;不能只看成是有…

C程序生成一定范圍內的隨機數

Random numbers just numbers that lie within a range and any of the numbers can occur. 隨機數只是在一個范圍內的數字&#xff0c;任何數字都可能出現。 In programming, we come through a lot of scenarios where we need to generate random numbers. Like for dice g…

提示丟失libgcc_s_dw2-1.dll問題

QT使用MinGW編譯器編譯中的的執行文件&#xff0c;執行問題 將qt中安裝的mingw編碼器的路徑添加到環境變量path (D:\Qt\Qt5.10.1\5.10.1\mingw53_32\bin)

第1章 數據庫系統概述

第1章 數據庫系統概述 1.1 數據庫系統簡介 數據庫技術的發展歷史 人工管理階段文件系統階段數據庫系統階段

淺談多線程和異步

最近很忙&#xff0c;因此拿出時間來寫博客也算是忙里偷閑了&#xff0c;繼承前面的一貫風格&#xff0c;繼續淺談胡侃。  最近在項目中遇到了Socket異步網絡傳輸的問題&#xff0c;所以沉下心來整理下。于是&#xff0c;先問了下度娘&#xff0c;結果找到了園友志良的一篇文…

查看Sql Server的log文件大小

SELECT DB_NAME(database_id) AS DatabaseName,Name AS Logical_Name,Physical_Name, (size*8)/1024 SizeMBFROM sys.master_filesWHERE DB_NAME(database_id) AdventureWorksGO 轉載于:https://www.cnblogs.com/top5/archive/2010/03/02/1676776.html

python調用帶參函數_Python | 帶有示例的函數調用類型

python調用帶參函數There are following types of function calls in python: python中有以下類型的函數調用&#xff1a; Call by value 按價值致電 Call by reference 通過參考電話 1)按價值致電 (1) Call by value ) When, we call a function with the values i.e. pass …

ffmpeg 命令添加文字水印

使用ffplay 預覽一下效果&#xff1a; ffplay -i cctvhttp.flv -vf “drawtextfontsize100:fontfileArial.ttf:tex t‘hello world’:x20:y20:fontcolorblue:alpha0.5” -x 640 -y 480 使用ffmpeg保存為文件 &#xff1a; ffmpeg -i cctvhttp.flv -vf “drawtextfontsize10…

jquery彈出層

這是一個彈出層的插件&#xff0c;有時候做東西的&#xff0c;經常會用到了&#xff0c;所以在次發一下&#xff0c;和大家分享一下&#xff01; [task]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/x…

MUL與IMUL區別(微機原理與接口技術 第2版)課后習題3.14、P123

MUL與IMUL的詳細區別 乘數位數隱含的被乘數乘積的存放位置舉例8位ALAX中MUL BL16位AXDX與AX中&#xff08;DX存放高16位、AX存放低16位&#xff09;MUL BX 課本P97例題 一&#xff09;、將以下指令中的立即數看作是無符號數實現相乘: MOV AL,0B4H ;ALB4H180 解釋以下&…