|
|
lock_guard (C++11) |
unique_lock (C++11) |
shared_lock (C++14) |
scoped_lock (C++17) |
#include
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
template
void lock_guard(){
int i = 0;
T lock;
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::lock_guard autolock(lock);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
int main(int argc, char* argv[])
{
::lock_guard();
::lock_guard();
::lock_guard();
}
#include
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
template
void unique_lock(){
int i = 0;
T lock;
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
template
void unique_lock_after_time() {
int i = 0;
T lock;
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock, std::chrono::milliseconds(1'000));
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
template
void unique_lock_until_time() {
int i = 0;
T lock;
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock, std::chrono::time_point < std::chrono::high_resolution_clock >(std::chrono::milliseconds(1'000)));
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
int main(int argc, char* argv[])
{
// 上锁和解锁操作,一直等待到获得锁
::unique_lock();
::unique_lock();
::unique_lock();
::unique_lock();
::unique_lock();
::unique_lock();
// 上锁和解锁操作,在一定时间内等待锁,否则超时
::unique_lock_after_time();
::unique_lock_after_time();
::unique_lock_after_time();
// 上锁和解锁操作,等待获得锁一直到某一个时间点,否则超时
::unique_lock_until_time();
::unique_lock_until_time();
::unique_lock_until_time();
}
#include
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
template
void scoped_lock(){
int i = 0;
T lock;
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::scoped_lock autolock(lock);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
template
void scoped_lock(){
int i = 0;
T lock;
U lock2;
auto fWThread = [&i, &lock, &lock2]() {
for (int k = 0; k < 10; k++) {
std::scoped_lock autolock(lock, lock2);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
template
void scoped_lock(){
int i = 0;
T lock;
U lock2;
V lock3;
auto fWThread = [&i, &lock, &lock2, &lock3]() {
for (int k = 0; k < 10; k++) {
std::scoped_lock autolock(lock, lock2, lock3);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
int main(int argc, char* argv[])
{
// 上锁和解锁操作,一直等待到获得锁
::scoped_lock();
::scoped_lock();
::scoped_lock();
// 上锁和解锁,同时对两个锁进行操作
::scoped_lock();
::scoped_lock();
// 上锁和解锁,同时对三个锁进行操作
::scoped_lock();
::scoped_lock();
// 同理,上锁和解锁,可同时对多个锁进行操作
}
#include
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
template
void share_lock() {
int i = 0;
T lock;
auto fRThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::shared_lock autolock(lock);
int j = i;
std::cout << std::this_thread::get_id() << " read: " << j << endl;
}
};
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock);
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread r1(fRThread);
std::thread w1(fWThread);
std::thread r2(fRThread);
r1.join();
r2.join();
w1.join();
}
template
void share_lock_until_time() {
int i = 0;
T lock;
auto fRThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::shared_lock autolock(lock, std::chrono::time_point < std::chrono::high_resolution_clock >(std::chrono::milliseconds(1'000)));
int j = i;
std::cout << std::this_thread::get_id() << " read: " << j << endl;
}
};
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock, std::chrono::time_point < std::chrono::high_resolution_clock >(std::chrono::milliseconds(1'000)));
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread r1(fRThread);
std::thread w1(fWThread);
std::thread r2(fRThread);
r1.join();
r2.join();
w1.join();
}
template
void share_lock_after_time() {
int i = 0;
T lock;
auto fRThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::shared_lock autolock(lock, std::chrono::milliseconds(1'000));
int j = i;
std::cout << std::this_thread::get_id() << " read: " << j << endl;
}
};
auto fWThread = [&i, &lock]() {
for (int k = 0; k < 10; k++) {
std::unique_lock autolock(lock, std::chrono::milliseconds(1'000));
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread r1(fRThread);
std::thread w1(fWThread);
std::thread r2(fRThread);
r1.join();
r2.join();
w1.join();
}
int main(int argc, char* argv[])
{
// 上锁和解锁操作,一直等待到获得锁
::share_lock();
// 上锁和解锁操作,在一定时间内等待锁,否则超时
::share_lock_after_time();
// 上锁和解锁操作,等待获得锁一直到某一个时间点,否则超时
::share_lock_until_time();
}
lock (C++11) |
try_lock (C++11) |
std::lock: 同时给多个锁上锁
std::try_lock:尝试同时给多个锁上锁
注意:这两个方法并不会去释放锁,需要自己主动去释放
#include
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
template
void lock(){
int i = 0;
T lock;
T lock2;
U lock3;
auto fWThread = [&i, &lock, &lock2, &lock3]() {
for (int k = 0; k < 10; k++) {
std::lock(lock, lock2, lock3);
std::lock_guard l1(lock, std::adopt_lock);// make sure lock is unlock finally
std::lock_guard l2(lock2, std::adopt_lock);// make sure lock2 is unlock finally
std::lock_guard l3(lock3, std::adopt_lock);// make sure lock3 is unlock finally
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
template
void try_lock(){
int i = 0;
T lock;
T lock2;
U lock3;
auto fWThread = [&i, &lock, &lock2, &lock3]() {
for (int k = 0; k < 10; k++) {
// -1 means success
if (-1 == std::try_lock(lock, lock2, lock3)){
int j = ++i;
std::cout << std::this_thread::get_id() << " write: " << j << endl;
lock.unlock();
lock2.unlock();
lock3.unlock();
}
else{
std::cout << std::this_thread::get_id() << " get lock failed" << endl;
}
}
};
std::thread w1(fWThread);
std::thread w2(fWThread);
w1.join();
w2.join();
}
int main(int argc, char* argv[])
{
::lock();
::try_lock();
}
defer_lock_t (C++11) |
try_to_lock_t (C++11) |
adopt_lock_t (C++11) |
以下分别是上面的常量实例化
defer_lock (C++11) |
try_to_lock (C++11) |
adopt_lock (C++11) |
它们用于指定std::lock_guard, std::unique_lock和std::shared_lock的锁定策略。
如:
std::mutex lock;
// 此处构造autolock时不会对lock上锁
std::unique_lock autolock(lock, std::defer_lock);
// 此处构造autolock时会尝试去获得锁,会立即返回
std::unique_lock autolock(lock, std::try_to_lock);
// 此处构造autolock时会假定lock已经上锁了
std::unique_lock autolock(lock, std::adopt_lock);
once_flag (C++11) |
call_once (C++11) |
once_flag用于call_once,once_flag标记是否被调用过。
· 若被调用的函数执行过了,那么这个标记就会标记为已调用;
· 若在调用的函数执行过程中抛出了异常,那么这个标记仍标记为未调用。
call_once指定只需要调用一次的函数入口
#include
#include
#include
std::once_flag flag1, flag2;
void simple_do_once()
{
std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
}
void may_throw_function(bool do_throw)
{
if (do_throw) {
std::cout << "throw: call_once will retry\n"; // this may appear more than once
throw std::exception();
}
std::cout << "Didn't throw, call_once will not attempt again\n"; // guaranteed once
}
void do_once(bool do_throw)
{
try {
std::call_once(flag2, may_throw_function, do_throw);
}
catch (...) {
}
}
int main()
{
std::thread st1(simple_do_once);
std::thread st2(simple_do_once);
std::thread st3(simple_do_once);
std::thread st4(simple_do_once);
st1.join();
st2.join();
st3.join();
st4.join();
std::thread t1(do_once, true);
std::thread t2(do_once, true);
std::thread t3(do_once, false);
std::thread t4(do_once, true);
t1.join();
t2.join();
t3.join();
t4.join();
}
/*
Simple example: called once
throw: call_once will retry
throw: call_once will retry
Didn't throw, call_once will not attempt again
*/