2016-10-27 6 views
3

知られているようstd::shared_timed_mutex(C++ 14)とstd::shared_mutex(C++ 17)は非常に長いstd::shared_lock S(読み出しオペレーション)のためstd::mutexを超える性能の利点を有し、そしてstd::shared_lock以上std::unique_lock秒だ場合。短い共有操作といくつかのユニークな操作のための共有ミューテックスのアプローチはありますか?

しかし、その読まれた操作のほとんど、彼らは短いですが、その後、std::mutexが速くなります場合でも - それが理由であるC++ 11 std::shared_mutex標準とstd::shared_timed_mutexがすぐに含まれていませんでした。

また、std::mutexの上に短い操作ためをパフォーマンス上の利点を持っている共有ミューテックスのいくつかの種類のいずれかのアプローチや実装がより多くの以下のようなだけではなく多くである読み込み、場合、ありますか?

std::unique_lock/std::shared_lock = 1/1 000 000 000 000

短い共有の操作といくつかのユニークな操作のための共有ミューテックスのいずれかのアプローチがありますか?

+1

IVEはしばらく前に私自身の簡単な '共有lock'スピンを書いた、多分それは高速です(IDK)https://github.com/domso/network/blob/master /network/rw_mutex.h https://github.com/domso/network/blob/master/src/rw_mutex.cpp – Domso

答えて

0

可能なアプローチは、重複したデータの使用です。これは、読者の数が多く、作家が少数である場合には非常に優れているはずです。私はその速くよりshared_mutex()場合は知らないが、代替

基本的な考え方です:ライターが別々ライター・コピーを変更することができますが

すべての読者は、読者コピーで動作します。変更をコミットするには、ライターオブジェクトを新しいリーダーオブジェクトに格納します。新しいリーダーオブジェクトはすべての新しいリーダーから取得されます。次のコミットは、今の古いreaderオブジェクトに格納されます。したがって、すべての古い読者がこのオブジェクトにロックを解除するまで、ライターは待つ必要があります。

簡単な例:

struct data{ 
    int a; 
}; 

struct secured_data { 
    data read[2]; 
    data write; 
    std::atomic<int> current = 0; 
    std::atomic<int> num_read[2] = 0; 

    std::mutex m; 

    data* read_lock() { 
     // increase reader-counter of current data-object 
     int c = current.load(); 
     num_read[c].fetch_add(1); 
     // return current copy 
     return &read + c; 
    } 

    void read_unlock(data* old) { 
     // decrease the old data-object (which was returned by read_lock()) 
     num_read[old - &read].fetch_sub(1); 


    } 

    data* lock() { 
     m.lock(); 
     // every modification happens on a seperate copy 
     write = read[current.load()]; 
     return &write; 
    } 

    void unlock() { 
     int c; 
     // wait until all readers using an old copy have released their lock 
     do { 
      c = current.load(); 
     } while (num_read[(c + 1) % 2].load() != 0); 
     // copy into new read-object 
     read[(c + 1) % 2] = write; 
     // swap read-object 
     // all readers now use an old version 
     current.store((c + 1) % 2); 
     m.unlock(); 
    } 
} 
+0

Thak you。しかし、 'num_read [c] .fetch_add(1);'は、Ping Pongでキャッシュラインを再生するRead-Modify-Write-operationです。つまり、 'num_read [c]'を含むキャッシュラインの排他的な状態それぞれの 'read_lock()'または 'read_unlock()'のCPUコアは、従来の 'std :: mutex'と同じで、' std :: mutex'よりも速くはありません。 (ライターなしの)読者だけが存在する場合、共有ロックは 'std :: mutex'よりも速くなるよう' load(任意のバリア) 'と' store(std :: memory_order_release) 'を使うことができます。 – Alex

関連する問題