【发布时间】:2014-07-16 01:12:57
【问题描述】:
以下代码导致我的应用程序冻结,即使该程序只有一个线程在运行。
semaphore 是 boost::shared_ptr<TMultiReadExclusiveWriteSynchronizer>。
if (semaphore)
{
semaphore->BeginWrite();
// Perform write operations on the shared object here.
semaphore->BeginRead();
semaphore->EndWrite();
// Perform read-only operations on the object, allowing other threads to also read.
semaphore->EndRead();
semaphore->BeginWrite(); // Program locks up here.
}
调试信息,供@v.ouddou 评论。
当我单步执行代码时,只有一个线程。顺便说一下,这是一个窗口应用程序,所以程序入口点是 WinMain,如果这很重要的话)。
当我踏入死亡线时(最后一个semaphore->BeginWrite(),程序冻结,如果我停止它,则有两个线程。我的主线程在汇编区,但调用堆栈是WaitForSingleObject-> WaitForSingleObjectEx->ZwWaitForSingleObject.
在RtlUserThreadStart的入口点还有第二个没有堆栈信息的线程。我认为这个线程只是为了让我能够暂停应用程序。此时,我的代码中没有任何意义来创建第二个线程。
【问题讨论】:
-
如果你可以在调试中运行,然后点击调试器的“暂停”,那么你可以检查进程中所有正在运行的线程的堆栈,并检查它们的位置。如果只有您的主线程,则堆栈可能没有意义,在线程处于取消调度调用的情况下。就像一个信号量等待一个信号。在这种情况下,线程进入等待队列,操作系统会立即安排其他事情,在这种情况下,您的堆栈通常没有意义。
-
基本上这似乎是 TMultiReadExclusiveWriteSynchronizer 实现中的一个错误。但是,您首先调用
BeginRead然后是写锁(EndWrite)然后才调用EndRead的用例无论如何都很奇怪。你能解释一下为什么需要这个吗? -
@v.oddou 添加了一些信息来回应你所说的。
-
@Daniel 我发布的代码只是一个最小的例子。在第一个
BeginWrite()之后,主线程打算修改一个共享对象。以下BeginRead(); EndWrite();旨在将锁从写锁降级为读锁。然后,该线程向子线程发送通知,告知它们发生了变化,它们需要响应新数据。在所有客户端都收到通知后,我们不再需要担心共享数据的变化,因此我们使用EndRead();释放读锁。最后的BeginWrite();只是为了复制问题。 -
重点是,'EndWrite(); BeginRead();` 具有相同的功能(离开写锁,进入读锁)。请注意,在升级或降级锁时,其他写入者总是有可能获得写锁! (这是避免死锁的固有功能)!
标签: c++ multithreading c++builder