[英]Simple Read Write Lock
我發現互聯網上的許多讀寫自旋鎖實現都不必要地復雜。 我在 c++ 中寫了一個簡單的讀寫鎖。
誰能告訴我,如果我遺漏了什么?
int r = 0;
int w = 0;
read_lock(void)
{
atomic_inc(r); //increment value atomically
while( w != 0);
}
read_unlock(void)
{
atomic_dec(r); // Decrement value atomically
}
write_lock(void)
{
while( (r != 0) &&
( w != 0))
atomic_inc(w); //increment value atomically
}
write_unlock(void)
{
atomic_dec(w); //Decrement value atomically
}
用法如下。
read_lock()
// Critical Section
read_unlock();
write_lock()
// Critical Section
write_unlock();
編輯:
感謝您的回答。 我現在將答案更改為原子等價物
如果線程同時訪問r
和w
,它們就會發生數據競爭。 如果 C++ 程序存在數據爭用,則程序的行為是未定義的。
C++ 標准不保證int
是原子的。 即使我們假設訪問int
的系統是原子的,即使在這樣的系統上, operator++
也可能不是原子操作。 因此,同時增量可能會“消失”。
此外,在write_lock
的循環write_lock
,另一個線程也可以在w
遞增之前結束它們的循環,從而允許多個同時寫入 - 我認為這個鎖應該防止這種情況。
最后,這似乎是實現自旋鎖的嘗試。 自旋鎖有優點也有缺點。 它們的缺點是它們在阻塞時消耗了線程的所有 CPU 周期。 這是非常低效的資源使用,不利於電池時間,也不利於其他可以使用這些循環的進程。 但如果等待時間很短,它可能是最佳的。
最簡單的實現是使用單個整數值。 -1 表示當前的寫入狀態,0 表示它沒有被讀取或寫入,正值表示它正在被那么多線程讀取。
使用 atomic_int 和 compare_exchange_weak (或強但弱就足夠了)
std::atomic_int l=0;
void write_lock() {
int v = 0;
while( !l.compare_exchange_weak( v, -1 ) )
v = 0; // it will set it to what it currently held
}
void write_unlock() {
l = 0; // no need to compare_exchange
}
void read_lock() {
int v = l.load();
while( v < 0 || !l.compare_exchange_weak(v, v+1) )
v = l.load();
}
void read_unlock() {
--l; // no need to do anything else
}
我認為這應該可以工作,並且有 RAII 對象,即創建一個自動 object 鎖定每種類型的構造並在破壞時解鎖。
可以這樣做:
class AtomicWriteSpinScopedLock
{
private:
atomic_int& l_;
public:
// handle copy/assign/move issues
explicit AtomicWriteSpinScopedLock( atomic_int& l ) :
l_(l)
{
int v = 0;
while( !l.compare_exchange_weak( v, -1 ) )
v = 0; // it will set it to what it currently held
}
~AtomicWriteSpinScopedLock()
{
l_ = 0;
}
};
class AtomicReadSpinScopedLock
{
private:
atomic_int& l_;
public:
// handle copy/assign/move issues
explicit AtomicReadSpinScopedLock( atomic_int& l ) :
l_(l)
{
int v = l.load();
while( v < 0 || !l.compare_exchange_weak(v, v+1) )
v = l.load(); }
}
~AtomicReadSpinScopedLock()
{
--l_;
}
};
在鎖定寫入值必須為 0 並且您必須將其交換為 -1,因此請繼續嘗試這樣做。
鎖定時讀取的值必須是非負數,然后您嘗試增加它,因此可能會對其他讀取器進行重試,而不是獲取鎖,而是設置其計數。
compare_exchange_weak 將第一個參數設置為交換失敗時實際持有的參數,第二個參數是您嘗試將其更改為的參數。 如果交換則返回 true,否則返回 false。
效率如何? 這是一個自旋鎖。 它會在等待時使用 CPU 周期,因此最好盡快可用:更新或讀取數據應為 swift。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.