use*_*542 4 winapi multithreading deadlock critical-section
我在我的程序中寻找可能的僵局,并且我怀疑以下内容.如果2个线程同时调用EnterCriticalSection并且线程#1在进入后立即调用DeleteCriticalSection会发生什么,那么仍然在EnterCriticalSection调用中的线程#2会发生什么?
谢谢.
In *_*ico 12
如果2个线程同时调用EnterCriticalSection并且线程#1在进入后立即调用DeleteCriticalSection会发生什么,那么仍然在EnterCriticalSection调用中的线程#2会发生什么?
两个线程不能同时进入临界区.那会破坏关键部分的目的.线程#1首先进入临界区,或者线程#2首先进入临界区.你在这里有两个可能的交错.
让我们说交错是这样的:
Thread 1 Thread 2
-------- --------
| |
| |
EnterCS() |
Lock Taken |
| |
| EnterCS()
| Blocked
| |
| |
DeleteCS() |
| |
| ???
|
...
在这种情况下,线程#2的状态根据MSDN未定义:
DeleteCriticalSection函数
备注
删除关键节对象会释放对象使用的所有系统资源.
删除临界区对象后,不要在除InitializeCriticalSection和InitializeCriticalSectionAndSpinCount之外的关键区域(如EnterCriticalSection,TryEnterCriticalSection和LeaveCriticalSection)上运行的任何函数中引用该对象.如果尝试这样做,可能会发生内存损坏和其他意外错误.
如果临界区在其仍然拥有时被删除,则等待已删除的临界区的所有权的线程的状态是未定义的.
因此,如果您不幸的是两个线程遇到上述交错,那么操作系统无法保证您的程序将继续按预期工作.例如,这可能包括死锁线程#2.
但如果交错是这样的:
Thread 1 Thread 2
-------- --------
| |
| |
| EnterCS()
| Lock Taken
| |
EnterCS() |
Blocked |
| |
| |
| ExitCS()
| Lock Released
| |
Unblocked |
LockTaken |
| |
DeleteCS() |
| |
| |
... ...
显然,由于线程#1被阻止,它不能删除临界区,直到线程#2离开临界区.然后假设没有其他线程进入临界区,线程#1将能够毫无问题地删除它.
您提出的方案基本上是竞争条件.根据线程的时间安排,它可能正常工作或导致不可预测的问题.在这种情况下,您必须重新构建代码,以便在所有感兴趣的线程释放临界区之后发生对关键部分的破坏.
在这个双线程场景中,一种解决方法是让线程#1离开临界区并等待所有其他线程先完成,然后再删除临界区.像这样的东西,例如:
// Pseudocode for exposition
void Thread1()
{
EnterCS();
// Do stuff
ExitCS();
WaitForThread2();
DeleteCS();
}
void Thread2()
{
EnterCS();
// Do stuff
ExitCS();
}
Run Code Online (Sandbox Code Playgroud)
现在,两个可能的交错看起来像这样:
Thread #2 acquires lock first: . Thread #1 acquires lock first:
.
Thread 1 Thread 2 . Thread 1 Thread 2
-------- -------- . -------- --------
| | . | |
| EnterCS() . EnterCS() |
| Lock Taken . Lock Taken |
| | . | |
EnterCS() | . // Do stuff EnterCS()
Blocked // Do stuff . | Blocked
| | . | |
| | . ExitCS() |
| ExitCS() . Lock Released |
| Lock Released . | |
| | . | Unblocked
Unblocked | . | Lock Taken
Lock Taken | . | |
| | . | // Do stuff
// Do stuff | . | |
| | . | ExitCs()
ExitCS() | . | Lock Released
Lock Released | . | |
| | . | |
| | . | |
WaitForThread2() --+ . WaitForThread2() --+
| . |
DeleteCS() . DeleteCS()
| . |
| . |
done . done
确切的实施WaitForThread2()取决于您的计划的性质,但肯定会涉及WaitForSingleObject()或其任何一个亲属.
| 归档时间: |
|
| 查看次数: |
3256 次 |
| 最近记录: |