我正在学习使用c++ lock_guard. 网上资源说我们不需要unlock手动,其次在出现异常的情况下mutex会自动释放,以便其他线程可以继续。
我正在尝试为第二种情况找到一个例子。基本上,当一个线程出现异常然后另一个线程应该继续时,我试图找到用例。
std::mutex m;
void f1() {
lock_guard<std::mutex> lock(m);
// some task that may raise exception
}
void f2() {
lock_guard<std::mutex> lock(m);
// some other task
}
int main() {
std::thread T1(f1);
T1.detach();
std::thread T2(f2);
T2.join();
}
Run Code Online (Sandbox Code Playgroud)
我在里面尝试了除以零的算术f1。但它使整个程序崩溃。然后我尝试在内部分配一个非常大的内存(例如new int[100000000000])f1。然后整个程序也崩溃了bad_alloc。
std::mutex m;
int a,b;
void f1() {
lock_guard<std::mutex> lock(m);
a = 1;
int * ptr = new int[10000000000]; // too large
b = 2;
}
void f2() {
lock_guard<std::mutex> lock(m);
cout << a <<" : "<<b <<endl;
}
int main() {
std::thread T1(f1);
T1.detach();
std::thread T2(f2);
T2.join();
}
Run Code Online (Sandbox Code Playgroud)
错误:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
如果我在有问题的代码段周围使用 try-catch 块,则thread2执行并且程序不会突然终止。但是现在T1没有释放锁(正如预期的那样try catch block)。
std::mutex m;
int a,b;
void f1() {
lock_guard<std::mutex> lock(m);
a = 1;
try {
int * ptr = new int[10000000000];
}catch(...) {
cout <<"new faild"<<endl;
}
// still locked
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); //2s
b = 2;
}
void f2() {
lock_guard<std::mutex> lock(m);
cout << a <<" : "<<b <<endl;
}
int main() {
std::thread T1(f1);
T1.detach();
std::thread T2(f2);
T2.join();
}
Run Code Online (Sandbox Code Playgroud)
我也不相信try-catch block上述情况,因为不使用的重点mutex.lock()/unlock()是优雅地处理和释放互斥锁。
我错过了什么吗?请举一个例子,一个线程发生异常(一些常见的异常情况),互斥锁被释放,其他线程继续执行。此外,主程序也不应该终止。
谢谢!
std::lock_guard是一个非常简单的类。它看起来像这样:
template <typename T>
class lock_guard
{
public:
lock_guard(T& mtx)
: mtx_{mtx}
{
mtx_.lock();
}
~lock_guard()
{
mtx_.unlock();
}
// not copyable
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
T& mtx_;
};
Run Code Online (Sandbox Code Playgroud)
如您所见,它所做的只是在其构造函数中锁定互斥锁并在其析构函数中解锁它。
这很有用,因为当对象析构函数因任何原因超出范围时会被调用,包括抛出异常时(如果它在某处被捕获;未捕获的异常将终止应用程序):
std::mutex mutex;
void thread_func()
{
try {
std::lock_guard<std::mutex> guard{mutex};
// mutex is now locked
throw std::exception{};
} catch (...) {
// mutex is already unlocked here.
}
// mutex is also unlocked here.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2538 次 |
| 最近记录: |