boost 递归锁_c++/boost互斥量与锁
線程之間的鎖有:互斥鎖、讀寫鎖、遞歸鎖、自旋鎖。一般而言,鎖的功能越強大,性能就會越低。
std::mutex-互斥鎖
互斥鎖用于控制多個線程對他們之間共享資源互斥訪問的一個信號量。也就是說是為了避免多個線程在某一時刻同時操作一個共享資源。例如線程池中的有多個空閑線程和一個任務隊列。任何是一個線程都要使用互斥鎖互斥訪問任務隊列,以避免多個線程同時訪問任務隊列以發生錯亂。
在某一時刻,只有一個線程可以獲取互斥鎖,在釋放互斥鎖之前其他線程都不能獲取該互斥鎖。如果其他線程想要獲取這個互斥鎖,那么這個線程只能以阻塞方式進行等待。
另有一種形式std::timed_mutex:超時機制的互斥鎖
std::shared_mutex-讀寫鎖
訪問者一般有兩種:讀者和寫者,寫者是一種排他的訪問方式,即獨占資源,讀者可以是共享的,就是說可以有多個線程同時去訪問某個資源,所以,讀寫鎖也可以叫做共享-獨占鎖。讀寫鎖比起mutex具有更高的適用性、更高的并行性,可以有多個線程同時占用讀模式的讀寫鎖,但是只能有一個線程占用寫模式的讀寫鎖。讀寫鎖最適用于對數據結構的讀操作次數多于寫操作的場合,因為,讀模式鎖定時可以共享,而寫模式鎖定時只能某個線程獨占資源。
另有一種形式std::shared_timed_mutex
std::recursive_mutex-遞歸鎖
所謂遞歸鎖,就是在同一線程上該鎖是可重入的,對于不同線程則相當于普通的互斥鎖。
另有一種形式std::recursive_timed_mutex
自旋鎖
自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對于互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。
實現自旋鎖:
class SpinMutex
{
std::atomic_flag flag;
public:
sSpinMutex()
{
flag=ATOMIC_FLAG_INIT;
}
void lock()
{
while(flag.test_and_set(std::memory_order_acquire));
}
void unlock()
{
flag.clear(std::memory_order_release);
}
};
std::lock_guard
嚴格基于作用域的鎖管理類模板,構造時是否加鎖是可選的(不加鎖時假定當前線程已經獲得鎖的所有權),析構時自動釋放鎖,所有權不可轉移,對象生存期內不允許手動加鎖和釋放鎖。
std::unique_lock
更加靈活的鎖管理類模板,構造時是否加鎖是可選的,在對象析構時如果持有鎖會自動釋放鎖,所有權可以轉移。對象生命期內允許手動加鎖和釋放鎖。
std::shared_lock
用于管理可轉移和共享所有權的互斥對象。
std::scoped_lock
類 scoped_lock提供便利RAII風格 機制的互斥包裝器,它在作用域塊的存在期間占有一或多個互斥。創建scoped_lock 對象時,它試圖取得給定互斥的所有權。控制離開創建 scoped_lock對象的作用域時,析構scoped_lock并以逆序釋放互斥。若給出數個互斥,則使用免死鎖算法,如同以std::lock。scoped_lock類不可復制。在處理多個互斥量時,特別簡單。
官方例子:
#include
#include
#include
#include
#include
#include
#include
struct Employee {
Employee(std::string id) : id(id) {}
std::string id;
std::vector<:string> lunch_partners;
std::mutex m;
std::string output() const
{
std::string ret = "Employee " + id + " has lunch partners: ";
for( const auto& partner : lunch_partners )
ret += partner + " ";
return ret;
}
};
void send_mail(Employee &, Employee &)
{
// simulate a time-consuming messaging operation
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void assign_lunch_partner(Employee &e1, Employee &e2)
{
static std::mutex io_mutex;
{
std::lock_guard<:mutex> lk(io_mutex);
std::cout << e1.id << " and " << e2.id << " are waiting for locks" << std::endl;
}
{
// use std::scoped_lock to acquire two locks without worrying about
// other calls to assign_lunch_partner deadlocking us
// and it also provides a convenient RAII-style mechanism
std::scoped_lock lock(e1.m, e2.m);
// Equivalent code 1 (using std::lock and std::lock_guard)
// std::lock(e1.m, e2.m);
// std::lock_guard<:mutex> lk1(e1.m, std::adopt_lock);
// std::lock_guard<:mutex> lk2(e2.m, std::adopt_lock);
// Equivalent code 2 (if unique_locks are needed, e.g. for condition variables)
// std::unique_lock<:mutex> lk1(e1.m, std::defer_lock);
// std::unique_lock<:mutex> lk2(e2.m, std::defer_lock);
// std::lock(lk1, lk2);
{
std::lock_guard<:mutex> lk(io_mutex);
std::cout << e1.id << " and " << e2.id << " got locks" << std::endl;
}
e1.lunch_partners.push_back(e2.id);
e2.lunch_partners.push_back(e1.id);
}
send_mail(e1, e2);
send_mail(e2, e1);
}
int main()
{
Employee alice("alice"), bob("bob"), christina("christina"), dave("dave");
// assign in parallel threads because mailing users about lunch assignments
// takes a long time
std::vector<:thread> threads;
threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob));
threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob));
threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice));
threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob));
for (auto &thread : threads) thread.join();
std::cout << alice.output() << '\n' << bob.output() << '\n'
<< christina.output() << '\n' << dave.output() << '\n';
}
總結
以上是生活随笔為你收集整理的boost 递归锁_c++/boost互斥量与锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 限定概率抽奖_圣诞节LOL紫色宝箱30连
- 下一篇: s3c2440移植MQTT