用
WaitReturn:=WaitForSingleObject(HMutex,0)
检查互斥对象HMutex的状态代码如下:
WaitReturn:=WaitForSingleObject(HMutex,0) //超时设置为0,只检查HMutex是否处于发信号状态
if WaitReturn=Wait_Object_0 then //处于发信号状态
begin
...
...
ReleaseMutex(HMutex); // //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end
else if WaitReturn=Wait_TimeOut then //超时
begin
...
...
ReleaseMutex(HMutex); // //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end
else if WaitReturn=Wait_Abandoned then //拥有该互斥对象的线程未释放此对象的所有权之前就已终止
begin
...
...
ReleaseMutex(HMutex); //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end;
WaitReturn:=WaitForSingleObject(HMutex,0)
检查互斥对象HMutex的状态代码如下:
WaitReturn:=WaitForSingleObject(HMutex,0) //超时设置为0,只检查HMutex是否处于发信号状态
if WaitReturn=Wait_Object_0 then //处于发信号状态
begin
...
...
ReleaseMutex(HMutex); // //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end
else if WaitReturn=Wait_TimeOut then //超时
begin
...
...
ReleaseMutex(HMutex); // //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end
else if WaitReturn=Wait_Abandoned then //拥有该互斥对象的线程未释放此对象的所有权之前就已终止
begin
...
...
ReleaseMutex(HMutex); //?????此处是否需要ReleaseMutex? 释放HMutex所有权
end;
if WaitReturn=Wait_Abandoned then //拥有该互斥对象的线程未释放此对象的所有权之前就已终止
如果某个线程未释放互斥对象的所有权就已终止,那其它线程是永远无法再获得该互斥对象的所有权了??
---------------------------
Wait_Object_0 后都需要 ReleaseMutex, 来释放互斥所有权的 if WaitReturn=Wait_Abandoned then //拥有该互斥对象的线程未释放此对象的所有权之前就已终止
如果某个线程未释放互斥对象的所有权就已终止,那其它线程是永远无法再获得该互斥对象的所有权了??
----------------------------
Wait_Abandoned 是互斥对象已经失效了,应该是不需要 ReleaseMutex
MSDN上没有说明 Wait_Abandoned 的是否必须释放的
但是给的Example Code 上是没有释放的MSDN CodeBOOL FunctionToWriteToDatabase(HANDLE hMutex)
{
DWORD dwWaitResult; // Request ownership of mutex.
dwWaitResult = WaitForSingleObject(
hMutex, // handle to mutex
5000L); // five-second time-out interval
switch (dwWaitResult)
{
// The thread got mutex ownership.
case WAIT_OBJECT_0:
__try {
// Write to the database.
} __finally {
// Release ownership of the mutex object.
if (! ReleaseMutex(hMutex))
{
// Deal with error.
} break;
} // Cannot get mutex ownership due to time-out.
case WAIT_TIMEOUT:
return FALSE; // Got ownership of the abandoned mutex object.
case WAIT_ABANDONED:
return FALSE;
} return TRUE;
}所以我觉得在 WAIT_ABANDONED的情况下, 是不需要ReleaseMutex的
一般ReleaseMutex也只有在Wait_Object_0 下处理
WAIT_ABANDONEDThe specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread and the mutex is set to nonsignaled.If the mutex was protecting persistent state information, you should check it for consistency.之前占有互斥对象的线程没有释放互斥对象,该线程就终止了。
case WAIT_ABANDONED:
return FALSE;
demo注释也说明获取到拥有权了。返回false,表示不成功。但实际上还是有人当作是成功的来用。
至于为什么没有release,可能还需要验证看看...
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SyncObjs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
f: Integer; {用这个变量协调一下各线程输出的位置}
gMutex: THandle;implementation{$R *.dfm}function ThreadFun1(p: Pointer): DWORD; stdcall;
begin
if WaitForSingleObject(gMutex, INFINITE) = WAIT_OBJECT_0 then
begin
Form1.Canvas.TextOut(0, 0, 'ThreadFun1.Exit');
Exit;
end; Result := 0;
end;function ThreadFun2(p: Pointer): DWORD; stdcall;
begin
case WaitForSingleObject(gMutex, INFINITE) of
WAIT_OBJECT_0: ReleaseMutex(gMutex);
Wait_Abandoned:
begin
// 只是证明 Wait_Abandoned有被执行到
Form1.Canvas.Lock;
Form1.Canvas.TextOut(0, 20, 'ThreadFun2.Wait_Abandoned');
Form1.Canvas.Unlock;
end;
else ;
end; Result := 0;
end;function ThreadFun3(p: Pointer): DWORD; stdcall;
var
I: Integer;
begin
for I := 0 to 10000 do
begin
if WaitForSingleObject(gMutex, INFINITE) = WAIT_OBJECT_0 then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(0, 40, IntToStr(i));
Form1.Canvas.Unlock;
ReleaseMutex(gMutex);
end;
end;
Result := 0;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(gMutex);
end;procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID: DWORD;
begin
CloseHandle(CreateThread(nil, 0, @ThreadFun1, nil, 0, ThreadID));
Sleep(100); // 保证第一个线程运行结束
CloseHandle(CreateThread(nil, 0, @ThreadFun2, nil, 0, ThreadID));
end;procedure TForm1.Button2Click(Sender: TObject);
var
ThreadID: DWORD;
begin
CloseHandle(CreateThread(nil, 0, @ThreadFun3, nil, 0, ThreadID));
end;procedure TForm1.FormCreate(Sender: TObject);
begin
gMutex := CreateMutex(nil, False, nil);
end;end.
第二个线程 主要为WaitForSingleObject出现 Wait_Abandoned的情况
第三个线程 主要为测试是否能拿到互斥对象测试第二个线程 wait_Abandoned的情况 如果没有ReleaseMutex,
第三个线程 第一次WaitForSingleObject 会出现 wait_Abandoned的情况,拿到互斥对象
下一次 WaitForSingleObject才会进入WAIT_OBJ ECT_0
如果第二个线程 wait_Abandoned的情况下ReleaseMutex
第三个线程 第一次WaitForSingleObject 就可以进入 WAIT_OBJ ECT_0所以wait_Abandoned 的情况下, 应该还是要ReleaseMutex
这种写法不对的。
得分两种情况, 第一次Wait_Abandoned的情况下, 如果ReleaseMutex该互斥对象,另外的线程是可以进入
WAIT_OBJ ECT_0,
如果 第一次Wait_Abandoned的情况下没有ReleaseMutex该互斥对象, 则另外的线程进入还需要先进入一次
Wait_Abandoned来拿到互斥所有权,然后该线程WaitForSingleObject下一次就可以进入WAIT_OBJ ECT_0