Comments (2)
一、同一个线程重复 lock 是未定义行为
在 lock 的文档中我们可以看到:
If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock.
翻译:如果一个线程已经拥有锁,那么再调用一次 lock 是未定义行为:例如,可能发生死锁。
这是很容易理解的,因为在多线程编程模型中我们知道,同一个线程连续 lock 两次会导致死锁。但是标准说了这是未定义行为,而不是明确规定会发生死锁,所以同一个调用两次 lock 可能发生死锁,也可能发生其他事情:包括但不限于抛出异常后推出,段错误,除零错误,代码的执行顺序紊乱,改变其他变量的值,甚至电脑着火,都有可能发生,当然也可能不产生任何错误,正常执行下去。
这就是未定义行为,只要你触犯了,他可以发生任何事,C++ 标准都不保护你。标准规定为未定义的,编译器都可以随便处理,发生任何事情都是你自己的责任,只不过对于 double-lock 而言大概率是“死锁”这一种情况罢了,正如空指针解引用大概率是”段错误“这一种情况一样。
之所以标准不规定是为了不要限制编译器厂商的创造力,例如官方文档后面举了个例子:“一个编译器实现可以检测到这种问题,并抛出 system_error 异常,方便用户调试。”
An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.
二、同一个线程重复 try_lock 也是未定义行为
在 try_lock 的文档中我们还可以看到:
If try_lock is called by a thread that already owns the mutex, the behavior is undefined.
翻译:如果一个线程已经拥有锁,那么再调用一次 try_lock 也是未定义行为。
没想到8,try_lock 也不允许。
你是不是已经想当然地认为 lock 会死锁,try_lock 就不会,即使是同一个线程,也能安全返回 false?
你是不是已经想当然地认为 try_lock 的内部实现是这样的了:
bool try_lock() {
if (!this->m_locked) {
lock();
return true;
}
return false;
}
如果标准都规定死了内部实现,不给编译器自由度,人家还怎么优化了?首先你“想当然”的这种 try_lock 内部实现就是不线程安全的。
记得我说的吗?发生未定义行为时编译器可以做任何事,包括不产生任何错误正常执行,但是打印一个错误的答案给你。
永远不要想当然,多看看 cppreference,官方文档说是未定义行为,就碰都不要去碰。不要依赖未定义行为,不要跟我说“汇编就是这样”,“我平时都是能稳定触发死锁/段错误/改变其他变量值”的。调试代码如果遇到发生任何离谱的行为时,首先检查你的代码,是不是有什么地方“想当然”了,触发未定义行为了,那发生任何事情都是合理的。
这就是 C++,听小彭老师说
所以如何修复这个未定义行为呢?标准说同一个线程多次调用 lock 或 try_lock 是未定义行为,但是他没说多个线程分别调用啊?所以你可以创建另一个线程去调用 try_lock,达到你“想当然”的那种“教学结果”。
#include <cstdio>
#include <mutex>
#include <thread>
std::mutex mtx1;
int main() {
if (mtx1.try_lock())
printf("succeed\n");
else
printf("failed\n");
std::thread t1([] { // 同一个线程不能 double-lock,也不能 double-try_lock,但没说另一个线程不可以
if (mtx1.try_lock())
printf("succeed\n");
else
printf("failed\n");
});
t1.join(); // join 在 unlock 前,保证 t1 里的 try_lock 是在 main 持有锁的情况下完成执行的
mtx1.unlock();
return 0;
}
运行结果:
succeed
failed
from course.
Get,感谢指出👍
from course.
Related Issues (20)
- 第三节课、ppt第54页,用 [=] 来捕获传参的lambda表达式为什么占4个字节? HOT 3
- std::string 使用迭代器,删除\r的时候,没办法删除干净 HOT 4
- 请教一个关于static和static inline的问题 HOT 1
- gpu任务能耗相关 HOT 1
- 请教一个问题,cmake如何生成XXXTargets.cmake文件 HOT 3
- Bbbbbbbbbb
- 请教老师第8课cuda并行部分10_stencil部分bug HOT 1
- 获取枚举名代码不适用于clang+msvc
- 报错:no suitable user-defined conversion from "CudaAllocator<int>" to "CudaAllocator<std::_Container_proxy>" exists HOT 3
- CudaAllocator 模板错误 HOT 1
- print 处理 unsigned long long int 输出异常 HOT 1
- print 函数打印模版特化问题 HOT 2
- course 09 compile error: nvcc fatal : A single input file is required for a non-link phase when an outputfile is specified HOT 2
- CudaAllocator报错 HOT 1
- bug : course/06/01_for/07/main.cpp
- Cuda自带的thrust没有 <thrust/universal_vector.h>文件 HOT 3
- 关于 07/03_prefetch/06 运行结果的疑问 HOT 2
- mtqueue.hpp中的代码细节问题
- Mac M1环境下使用并发链表进行测试,4线程对链表push,4线程对链表pop,会出现重复delete同一个节点的错误
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from course.