std::lock
template<class Mutex1, class Mutex2, class ... Mutexes>
void lock(Mutex1& a, Mutex2& b, Mutexes&... cde);
鎖定作爲參數傳進來的對象,如果有必要調用線程進行阻塞;
std::lock通過使用lock、try_lock、unlock來鎖定對象,返回之前確保所有的對象都上鎖,並且沒有產生死鎖
如果不能鎖定所有對象,在失敗之前會前之前成功鎖定的對象解鎖;
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex foo, bar;
void TaskA() {
lock(foo, bar);
cout<<"TaskA "<<endl;
foo.unlock();
bar.unlock();
}
void TaskB() {
lock(bar, foo);
cout<<"TaskB"<<endl;
bar.unlock();
foo.unlock();
}
int main(void) {
thread threads[2];
threads[0] = thread(TaskA);
threads[1] = thread(TaskB);
for (int i = 0; i < 2; ++i) {
threads[i].join();
}
return 0;
}
要注意,可能會產生死鎖
Note that before replacing the individual locks by the call to std::lock, if task_a locked foo while task_b locked bar, neither could ever get the second lock, causing a deadlock.
std::try_lock
template<class Mutex1, class Mutex2, class... Mutexes>
int try_lock(Mutex1& a, Mutex2& b, Mutexes... cde);
Attempts to lock all the objects passed as arguments using their try_lock member functions (non-blocking).
返回值:
如果都成功鎖住則返回-1,否則返回失敗加鎖的對象index,0 for a, 1 for b, ...;
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex foo, bar;
void TaskA() {
foo.lock();
cout<<"Task A"<<endl;
bar.lock();
//
foo.unlock();
bar.unlock();
}
void TaskB() {
int x = try_lock(bar, foo);
if (x == -1) {
cout<<"task b"<<endl;
foo.unlock();
bar.unlock();
} else {
cout<< "task b failed: mutex"<<(x ? "foo" :\
"bar ")<<" locked"<<endl;
}
}
int main(void) {
thread t1(TaskA);
thread t2(TaskB);
t1.join();
t2.join();
return 0;
}
要注意:
Either mutex may appear locked to task_b, or both tasks may succeed in either order (text can appear intermingled on failure).
std::once_flag;
Flag argument tyep for call_once;
once_flag作爲call_once的參數
struct once_flag {
constecxpr once_flag() noexcept;
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
};
std::call_once
template<class Fn, clas... Args>
void call_once(once_flag& flag, Fn&& fn, Args&&... args);
int winner;
void SetWinner(int x) {
winner = x;
}
std::once_flag winner_flag;
void WaitThousandSeconds(int id) {
for (int i = 0; i < 1000; ++i) {
std::this_thread.::sleep_for(std::chrono::milliseconds(1));
}
std::call_once(winner_flag, SetWinner, id);
}