リーダライタプロセスは、次のようなデータ構造を共有します:
セマフォrw_mutex = 1 。 セマフォ、ミューテックス = 1 。 int型 read_count = 0 ;
セマフォミューテックスとrw_mutexは1に初期化されます。read_countは0に初期化されます。
セマフォrw_mutexは、リーダライタプロセスの両方に共通しています。ミューテックスセマフォは、変数の読み取りカウントが更新されたときに相互排除を確実にするために使用されます。read_count変数には、現在のオブジェクトを読んでいるどのように多くのプロセスを追跡します。作家のための相互排他セマフォとしてセマフォrw_mutex機能。また、入力するか、クリティカルセクションを出て最初または最後のリーダーで使用されています。これは、他の読者が自分のクリティカルセクションにありながら出入り読者によって使用されていません。
書式#include <スレッド> の#include <ミューテックス> 書式#include <condition_variable> 使用して 名前空間はstd; クラスセマフォ{ パブリック: セマフォ(INT count_ = 0 ):カウント(カウント_){} インラインボイド待ち(){ std :: unique_lockの <はstd ::ミューテックス> ロック(MTX); cv.wait(ロック、[ これ ](){ 戻りカウント> 0 ;}); カウント - ; } インラインボイド通知(){ std :: unique_lockの <はstd ::ミューテックス> ロック(MTX); カウント ++ ; cv.notify_one(); } プライベート: std ::ミューテックスMTX; std :: condition_variable CV; int型カウント; }。 セマフォrw_mtx(1)。// リーダライタの両方に共通 セマフォMTX(1); // 変数read_countが更新された相互排除を保証する int型 read_count = 0 ; int型の値= 0 ; // 読者と作家のための値 ボイドリーダー(){ mtx.wait(); ++ read_count; もし(read_count == 1 ) rw_mtx.wait(); mtx.notify(); 裁判所未満 << " 読み込み" <<値<< ' \ nを' ; mtx.wait(); - read_count; もし(read_count == 0 ) rw_mtx.notify(); mtx.notify(); } 無効ライター(int型V){ rw_mtx.wait(); 値 = V; COUTは << " 書き込み" V << << ' \ nを' ; rw_mtx.notify(); } INT {main()の スレッドreader1(リーダー)。 スレッドreader2(リーダー)。 スレッドreader3(リーダー)。 スレッドwriter1(作家、1 ); reader1.join(); reader2.join(); reader3.join(); writer1.join(); リターン 0 ; }
リーダライタロック
読者ライターの問題とその解決策を提供するために、一般化されている リーダライタロックを いくつかのシステムで。リーダライタロックを獲得することはロックのモードを指定する必要があります。読み取りまたは書き込みアクセスをどちらか。プロセスが共有データを読み取るためにのみたい場合は、読み取りモードでリーダライタロックを要求します。共有データを変更したいプロセスが書き込みモードでロックを要求しなければなりません。複数のプロセスを同時に読み出しモードにおけるリーダライタロックを獲得することを許可されているが、排他的アクセスが作家のために必要とされる唯一の方法は、書き込みのためにロックを取得してもよいです。
C ++ 17には、導入 shared_mutexの ほとんどのC ++コンパイラで利用できるようになりました実装を。
通常のミューテックスは、3つの方法を公開している間: lock
、 unlock
および try_lock
、shared_mutexは3以上を追加します。 lock_shared
、 unlock_shared
、 try_lock_shared
。最初の3つの方法は、通常のミューテックスと全く同じように機能します。ミューテックスがロックされている場合、それがアンロックされるまで、すなわち、他のすべてのスレッドが待機します。共有バージョンはもう少し複雑です。
読者が常に永遠に待っているの書き込みにつながる可能性が待っているの作家があっても、共有ミューテックスをロックすることができますので、の実装は、 shared_mutex
プログラマがこの問題について考えることなく、それを使用することができます特別なアルゴリズムを使用しています。esily説明することができる1つのシナリオがあります:呼び出して何のスレッドが存在しない場合 lock
、これまでは、呼び出すすべてのスレッドでは lock_shared
、これまで待たずに続行することが許可されます。
書式#include <iostreamの> の#include <スレッド> の#include <shared_mutex> 使用して 名前空間はstdを、 shared_mutexのMTX; int型の値= 0 ; // 読者と作家のための値 ボイドリーダー(){ // shared_lock <=>)(mtx.unlock_shared)(mtx.lock_shared shared_lock <shared_mutex> readLock(MTX)。 裁判所未満 << " 読み込み" <<値<< ' \ nを' ; } 無効ライター(int型V){ // shared_lock <=> mtx.lock()、mtx.unlock()、 // ここにもlock_guard使用することができます unique_lockの<shared_mutex> WRITELOCK(MTX)を、 値 = V; COUTは << " 書き込み" V << << ' \ nを' ; } INT {main()の スレッドreader1(リーダー)。 スレッドreader2(リーダー)。 スレッドreader3(リーダー)。 スレッドwriter1(作家、1 ); reader1.join(); reader2.join(); reader3.join(); writer1.join(); リターン 0 ; }
参照
オペレーティングシステムの概念Essentialsの、第二 - Abraham Silberschatz氏
https://stackoverflow.com/questions/244316/reader-writer-locks-in-c
https://ncona.com/2019/03/read-write-mutex-with-shared_mutex/