2016-11-12 63 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(); 
} 

這實際上是一個更簡單,這是很好的。