2016-11-12 45 views
0

我的程序处于死锁状态,我不知道为什么,当我在调试器中运行它时不会这样做,所以我的第一个疑犯是我的rwLock,我写了自己的版本,因为我只想使用标准库 - 我不认为直到C++ 17才包含rwLock - 这不是我通常所做的事情。这个rwLock实现有什么问题吗?

class RwLock 
{ 
    std::mutex mutex; 
    std::unique_lock<std::mutex> unique_lock; 
    std::condition_variable condition; 

    int reading_threads; 
    bool writing_threads; 

public: 
    RwLock(); 
    ~RwLock(); 

    void read_lock(); 
    void read_unlock(); 

    void write_lock(); 
    void write_unlock(); 
}; 


RwLock::RwLock() : 
    mutex(), 
    unique_lock(mutex, std::defer_lock), 
    condition(), 
    reading_threads(0), 
    writing_threads(false) 
{ 
} 

RwLock::~RwLock() 
{ 
    //TODO: find something smarter to do here. 
    write_lock(); 
} 

void RwLock::read_lock() 
{ 
    unique_lock.lock(); 

    while(writing_threads) 
    { 
     condition.wait(unique_lock); 
    } 

    ++reading_threads; 
    unique_lock.unlock(); 
} 

void RwLock::read_unlock() 
{ 
    unique_lock.lock(); 

    if(--reading_threads == 0) 
    { 
     condition.notify_all(); 
    } 

    unique_lock.unlock(); 
} 

void RwLock::write_lock() 
{ 
    unique_lock.lock(); 

    while(writing_threads) 
    { 
     condition.wait(unique_lock); 
    } 

    writing_threads = 1; 

    while(reading_threads) 
    { 
     condition.notify_all(); 
    } 

    unique_lock.unlock(); 
} 

void RwLock::write_unlock() 
{ 
    unique_lock.lock(); 
    writing_threads = 0; 
    condition.notify_all(); 
    unique_lock.unlock(); 
} 
+0

'while(reading_threads){condition.notify_all(); “如果有任何读者,这将永远等待。你永远不会解锁锁,因此永远不会给读者一个减少'read_threads'的机会。看起来像复制/粘贴到我的错误 - 我敢打赌,你的意思是'condition.wait'在这里,而不是'notify_all' –

+0

@IgorTandetnik我从另一个网站复制了这个,并修改它,所以是的。我有一种感觉,那就是问题的原因,但这两种情况对我来说都不会对我产生很大的影响。 –

+0

'shared_timed_mutex'存在于C++ 14中 – Yakk

回答

0

std::shared_timed_mutex存在于C++ 17之前:在C++中14。

使用它,它会有更少的错误,几乎肯定会更快。

C++ 17介绍shared_mutex可以更快。但我强烈怀疑你使用C++标准原语实现比shared_timed_mutex更快的共享rwlock的能力。

0

看起来除了在这两个代码的问题很好:

void RwLock::write_lock() 
{ 
    unique_lock.lock(); 

    while(writing_threads) 
    { 
     condition.wait(unique_lock); 
    } 

    writing_threads = 1; 

    while(reading_threads) 
    { 
     condition.notify_all(); 
    } 

    unique_lock.unlock(); 
} 

首先,增加writing_threads为时已晚。读者可以偷偷进来。有可能你不介意甚至不想要这样,但通常这是不希望的。

其次,您在最后的while循环中的通知应该是wait。把它放在一起,我们得到:

void RwLock::write_lock() 
{ 
    unique_lock.lock(); 

    ++writing_threads; 

    while((writing_threads > 1) || (reading_threads > 0)) 
    { 
     condition.wait(unique_lock); 
    } 

    unique_lock.unlock(); 
} 

void RwLock::write_unlock() 
{ 
    unique_lock.lock(); 
    --writing_threads; // note change here 
    condition.notify_all(); 
    unique_lock.unlock(); 
} 

这实际上是一个更简单,这是很好的。