Boost.shared_mutex書き込み優先度、読み取り共有、相互排他



Boost Shared_mutex Write Priority



shared_mutexは読み取り/書き込みロックであり、一般的に使用される排他ロックmutexとは異なります。shared_mutexは共有および排他的共存ロックであり、読み取り/書き込みロックメカニズムを実装します。つまり、通常、複数の読み取りスレッドと1つの書き込みスレッドが使用されます。共有領域の読み取り操作がより頻繁で、書き込み操作が少ない状況。

ミューテックスと比較して、読み取り/書き込みロックは、より高い適用性とより高い並列性を備えています。複数のスレッドが読み取りモードで同時に読み取り/書き込みロックを占有できますが、書き込みモードで読み取り/書き込みロックを占有できるのは1つのスレッドのみです。ロックの基本的なルールは次のように要約できます。<書き込み優先度、読み取り共有、相互排除>、具体的には読み取り/書き込みロックの3つの状態として表されます。
(1)読み取り/書き込みロックが書き込みロック状態の場合、ロックをロックしようとするすべてのスレッドは、ロックがロック解除される前にブロックされます。 (クロスエクスクルーシブ)
(2)読み取​​り/書き込みロックが読み取りロック状態の場合、読み取りモードでロックしようとするすべてのスレッドはアクセスできますが、書き込みモードでロックしようとするスレッドはブロックされます。 (読み取り共有、相互排除)
(3)読み取り/書き込みロックが読み取りモードのロック状態にあるときに、別のスレッドが書き込みモードでロックしようとすると、通常、読み取り/書き込みロックは後続の読み取りモードロック要求をブロックします。読み取りモードロックの期間占有。待機中の書き込みモードのロック要求が長時間ブロックされます。 (最初に書く)

注:実際、リーダーとライターの問題には、リーダーファーストとライターファーストの2つのモードがありますが、ブーストでのshared_mutexのデフォルトの実装はライターファーストです。私たちは常に読みたいので、これは実際には理にかなっています。受信したデータは最新であり、ライターが優先されることを意味します。



以下では、boost :: shared_mutexのアプリケーション例を使用して、そのロックメカニズムを反映しています。この例では、2つのリーダースレッドと2つのライタースレッドを作成します。プログラムの実際の実行結果は、shared_mutexのアプリケーションを直接反映しています。

#include #include #include using namespace boost int g_num = 10 //Global variable, the writer changes the global variable, the reader reads the global variable shared_mutex s_mu //Global shared_mutex object //Write thread void read_(std::string &str) { const char* c = str.c_str() while (1) { { shared_lock m(s_mu) //Read lock, shared_lock printf('Thread %s enters the critical section, global_num = %d ', c, g_num) boost::this_thread::sleep(boost::posix_time::seconds(1)) //sleep for 1 second, give enough time to see if other threads can enter the critical area printf('Thread %s left the critical section... ', c) } boost::this_thread::sleep(boost::posix_time::seconds(1)) //slpp 1 second after the reader thread leaves (change this value to see different effects) } } //Read thread void writer_(std::string &str) { const char* c = str.c_str() while (1) { { unique_lock m(s_mu) //write lock, unique_lock ++g_num printf('Thread %s enters the critical section, global_num = %d ', c, g_num) boost::this_thread::sleep(boost::posix_time::seconds(1)) //sleep for 1 second, so that other threads have time to enter the critical zone printf('Thread %s left the critical section... ', c) } boost::this_thread::sleep(boost::posix_time::seconds(2)) //slpp 2 seconds after the write thread leaves, here is one second longer than the read thread because if it is also 1 second, those two writes When threads request a lock together, the reader thread will starve } } int main() { std::string r1 = 'read_1' std::string r2 = 'read_2' std::string w1 = 'writer_1' std::string w2 = 'writer_2' boost::thread_group tg tg.create_thread(bind(read_, boost::ref(r1))) //Two readers tg.create_thread(bind(read_, boost::ref(r2))) tg.create_thread(bind(writer_, boost::ref(w1))) //Two writers tg.create_thread(bind(writer_, boost::ref(w2))) tg.join_all() return 0 }

実行結果から確認できます。



リーダーがshared_mutexを取得すると、他のリーダーが同時にクリティカルセクションに入ることができます

ライターがshared_mutexを取得した場合、他のライターまたはリーダーはクリティカルセクションに入ることができません。つまり、同時にクリティカルセクションに入ることができるのは1人のライターだけです。