仅使用关键部分的读/写锁定会导致死锁
Read/Write lock using only critical section causes deadlock
在用相同的标题和答案浏览了这个问题之后,我想尝试一些应该只使用关键部分才能真正工作的东西,因此应该比现有解决方案快得多(使用其他内核对象,如互斥锁或信号量(
以下是我的读/写锁定/解锁功能:
#include <windows.h>
typedef struct _RW_LOCK
{
CRITICAL_SECTION readerCountLock;
CRITICAL_SECTION writerLock;
int readerCount;
} RW_LOCK, *PRW_LOCK;
void InitLock(PRW_LOCK rwlock)
{
InitializeCriticalSection(&rwlock->readerCountLock);
InitializeCriticalSection(&rwlock->writerLock);
}
void ReadLock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->readerCountLock); // In deadlock 1 thread waits here (see description below)
if (++rwlock->readerCount == 1)
{
EnterCriticalSection(&rwlock->writerLock); // In deadlock 1 thread waits here
}
LeaveCriticalSection(&rwlock->readerCountLock);
}
void ReadUnlock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->readerCountLock);
if (--rwlock->readerCount == 0)
{
LeaveCriticalSection(&rwlock->writerLock);
}
LeaveCriticalSection(&rwlock->readerCountLock);
}
int WriteLock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->writerLock); // In deadlock 3 threads wait here
}
void WriteUnlock(PRW_LOCK rwlock)
{
LeaveCriticalSection(&rwlock->writerLock);
}
这是一个线程函数。从main
调用InitLock (&g_rwLock);
后,我创建了五个线程来尝试这些锁。
void thread_function()
{
static int value = 0;
RW_LOCK g_rwLock;
while(1)
{
ReadLock(&g_rwlLock);
BOOL bIsValueOdd = value % 2;
ReadUnlock(&g_rwlLock);
WriteLock(&g_rwlLock);
value ++;
WriteUnlock(&g_rwlLock);
}
}
理想情况下,此代码应该永远运行而不会遇到任何问题。但令我失望的是,它并不总是运行。有时它会陷入僵局。我编译了这个并在Windows XP上运行它。要使用线程池创建线程,我使用的是第三方库。因此,这里不能给出所有涉及大量初始化例程和其他东西的代码。
但是为了缩短故事,我想知道是否有人通过查看上面的代码可以指出这种方法有什么问题?
我在上面的代码中评论了,当死锁发生时,每个线程(五个线程中(都在等待。(我通过将调试器附加到死锁进程来发现它(
任何输入/建议都非常棒,因为我已经坚持了很长时间了(贪婪地让我的代码运行得比以往任何时候都快(。
到目前为止发现了
两件事:
- 初始化每个线程中的关键部分,这是不允许的(行为未定义(
- 您不能将关键部分保留在与进入该部分的线程不同的线程中("如果线程在没有指定关键部分对象的所有权时调用
LeaveCriticalSection
,则会发生错误,可能导致另一个使用EnterCriticalSection
的线程无限期等待。
后者符合你看到的僵局。
一旦你同时有多个读取器,你就无法控制它们调用ReadUnlock
的顺序,所以你不能确保第一个线程,这是唯一允许调用LeaveCriticalSection
的线程,是最后一个输出的线程。
这样
它就无法正常运行。
- 让 1 个线程进入 ReadLock((,让它通过 ++ 指令,但在进入编写器 CS 之前暂停它
- 另一个线程进入 WriteLock(( 并成功进入 writerCS
所以现在我们有读者计数 = 1 并同时运行写入器。 请注意,读取器在 EnterCriticalSection(&rwlock->writerLock( 上死锁
相关文章:
- 同一互斥锁顺序上的锁定和解锁是否一致?
- Windows 在 C++ 中锁定和解锁事件
- 在任何地方对C++中所有并行线程中的所有锁定和解锁实例使用相同的 std::mutex 和 lock 对象
- 线程锁定互斥锁的速度比 std::conditional_variable::wait() 快
- 如何在锁定互斥锁的情况下处理主线程中的信号
- 在C++中锁定和解锁文件
- 简单的读写锁
- 静音锁定和解锁时间差
- 优化读/写锁的实现
- 提升::Asio 写锁
- 保持 std::mutex 锁定/解锁公开的基本原理
- C++ pthreads - 尝试锁定互斥锁进行读取时崩溃
- 如何从更基本的同步原语中创建多读/单写锁
- 此用例是否需要读写锁
- 锁定/解锁私有函数中的互斥锁
- 什么'如果pthread_cond_wait自己这样做,那么锁定和解锁互斥锁的意义就在于什么
- 我们什么时候使用QMutexLocker重新锁定和解锁
- 在线程内部函数上使用哪种保护方法(互斥,读写锁.)
- pthread互斥锁定和解锁每个变量
- 我们可以在socket Map上使用读写锁吗?