2016-11-12 7 views
0

私のプログラムはデッドロックしていますが、私はデバッガで実行するとそれができないので、最初の疑いがrwLockなので、なぜ私は自分のバージョンを書いたのでしょうか?ライブラリ - 私はrwLockがC++ 17まで含まれているとは思わない - これは私が普通にやることではない。この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(); } '読者があればそれは永遠に待つだろう。ロックを解除することは決してないので、読者に 'reading_threads'を減らす機会を与えることは決してありません。私にコピー/ペーストのエラーのように見える - 私は 'notify_all'ではなく' condition.wait'をここに入れることを意味すると確信しています –

+0

@IgorTandetnik私は別のウェブサイトからこれをコピーして修正しました。私はラインが問題だと感じましたが、どちらの状況も正直言って私には意味がありません。 –

+0

'shared_timed_mutex'はC++で存在します14 – Yakk

答えて

0

は、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をインクリメントします。読者が潜んでいるかもしれません。あなたが気にしない、あるいはこれを望んでいる可能性もありますが、通常これは望ましくありません。

第2に、最後の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(); 
} 

これは実際には少しシンプルです。

関連する問題