在逗号运算符的 LHS 中初始化匿名互斥锁持有类实例
假设我有这样的代码:
#include "boost/thread/mutex.hpp"
using boost::mutex;
typedef mutex::scoped_lock lock;
mutex mut1, mut2;
void Func() {
// ...
}
void test_raiicomma_1() {
lock mut1_lock(mut1);
Func();
}
void test_raiicomma_2() {
(lock(mut1)), Func();
}
void test_raiicomma_3() {
(lock(mut1)), (lock(mut2)), Func(); // Warning!
}
int main()
{
test_raiicomma_1();
test_raiicomma_2();
test_raiicomma_3();
return 0;
}
如果从多个线程调用函数 test_raiicomma_1
(),它会锁定互斥体以防止任何其他线程也在该处调用 Func()
同一时间。当变量 mut1_lock
被构造时,互斥锁被锁定,当它超出范围并被破坏时,互斥锁被释放。
这工作得很好,但作为一种风格问题,需要给持有锁的临时对象命名让我很恼火。函数 test_raiicomma_2()
尝试通过初始化锁定对象并在一个表达式中调用函数 Func()
来避免这种情况。
在 Func()
返回后,直到表达式末尾才会调用临时对象析构函数,这是否正确? (如果是这样,您认为值得使用这个习惯用法,还是在单独的语句中声明锁总是更清晰?)
如果函数 test_raiicomma_3()
需要锁定两个互斥体,则为正确的是,互斥体将在调用 Func() 之前按顺序锁定,并在之后释放,但不幸的是可能会以任一顺序释放?
Suppose I have code something like this:
#include "boost/thread/mutex.hpp"
using boost::mutex;
typedef mutex::scoped_lock lock;
mutex mut1, mut2;
void Func() {
// ...
}
void test_raiicomma_1() {
lock mut1_lock(mut1);
Func();
}
void test_raiicomma_2() {
(lock(mut1)), Func();
}
void test_raiicomma_3() {
(lock(mut1)), (lock(mut2)), Func(); // Warning!
}
int main()
{
test_raiicomma_1();
test_raiicomma_2();
test_raiicomma_3();
return 0;
}
If the function test_raiicomma_1
() were called from multiple threads, it locks a mutex to prevent any other thread also calling Func()
at the same time. The mutex is locked when the variable mut1_lock
is constructed, and released when it goes out of scope and is destructed.
This works perfectly fine, but as a matter of style, needing to give a name to the temporary object holding the lock irked me. The function test_raiicomma_2()
attempts to avoid this, by inialising the lock object and calling the function Func()
within one expression.
Is it correct that the temporary object destructor will not be called until the end of the expression, after Func()
has returned? (If so, do you think it's ever worthwhile to use this idiom, or is it always clearer to declare the lock in a separate statement?)
If the function test_raiicomma_3()
needs to lock two mutexes, is it correct that the mutexes will be locked in order before calling Func()
, and released afterwards, but may unfortunately be released in either order?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
确保构造函数和析构函数都被调用,因为它们有副作用,并且销毁只会在完整表达式的末尾发生。
我相信它应该有效
逗号总是从左到右评估,作用域内的自动变量总是以创建的相反顺序被销毁,所以我认为甚至可以保证它们也以(正确的)顺序释放
正如litb在评论中指出的那样,你需要大括号或者你的表达式将被解析为声明。
我不这么认为,不,为了非常非常小的收益而感到困惑......
我总是使用非常显式的锁和非常显式的作用域(通常在块内额外的 {}),如果没有“特殊”代码,体面的线程安全代码就已经足够困难了,并且在我看来保证了非常清晰的代码。
当然是YMMW:)
It is guaranteed that both constructor and destructor are called, as they have side effects, and that destruction will only happen at the end of a full expression.
I believe it should work
Comma is always evaluated left to right, and automatic variables within a scope are always destroyed in reverse order of creation, so I think it's even guaranteed they are released in the (correct) order too
As litb points out in the comments, you need braces or your expression will be parsed as a declaration.
I don't think so no, to confusing for very, very little gain...
I always use very explicit locks, and very explicit scopes (often extra {} within a block), decent threadsafe code is hard enough without 'special' code, and warrants very clear code in my opinion.
YMMW of course :)
虽然不必提供有意义的名称可以减轻您的负担,但它会增加找出该代码应该做什么的任务,从而增加代码读者的负担 - 在决定是否
test_raiicomma_3 实际上按照其作者所设想的方式工作。
一段代码只写一次,但被读10次、100次、1000次,那么写所有的锁真的那么难吗?
While not having to give meaningful names frees you of a burden, it will add the task to find out what that code is supposed to do to the burdens of readers of your code -- atop the task to decide whether
test_raiicomma_3
actually works the way its writer seems to have supposed.Given that a piece of code is written once, but is read 10, 100, or 1000 times, is it really so hard to write all the locks?
互斥锁将以从左到右的顺序创建,并在完整表达式结束时释放。您可以这样写:
根据 C++ 标准 5.18/1,互斥体将按正确的顺序被销毁:
Mutexes will be created in left-to-right order and released in the end of full expression. You could write:
Mutexes will be destroyed in proper order according to C++ Standard 5.18/1: