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);
}