return 是原子的吗?我应该在 getter 中使用临时值以保证线程安全吗?
这里是否需要使用临时变量来保证线程安全?
int getVal() {
this->_mutex.lock();
int result = this->_val;
this->_mutex.unlock();
return result;
}
我给你简单的RAII测试函数的反汇编
int test()
{
RAIITest raii; //let's say it's a scoped lock
return 3;
}
{
0x004013ce <_Z4testv>: push %ebp
0x004013cf <_Z4testv+1>: mov %esp,%ebp
0x004013d1 <_Z4testv+3>: sub $0x28,%esp
return 3;
0x004013d4 <_Z4testv+6>: lea -0x18(%ebp),%eax
0x004013d7 <_Z4testv+9>: mov %eax,(%esp)
0x004013da <_Z4testv+12>: call 0x4167a0 <_ZN8RAIITestD1Ev> //here destructor is called
0x004013df <_Z4testv+17>: mov $0x3,%eax //here result is pushed onto the stack
}
0x004013e4 <_Z4testv+22>: leave
0x004013e5 <_Z4testv+23>: ret
编译器是gcc/g++ 3.4.5
Is it necessary to use a temporary here to be thread-safe?
int getVal() {
this->_mutex.lock();
int result = this->_val;
this->_mutex.unlock();
return result;
}
I'll give you disassembly of simple RAII test function
int test()
{
RAIITest raii; //let's say it's a scoped lock
return 3;
}
{
0x004013ce <_Z4testv>: push %ebp
0x004013cf <_Z4testv+1>: mov %esp,%ebp
0x004013d1 <_Z4testv+3>: sub $0x28,%esp
return 3;
0x004013d4 <_Z4testv+6>: lea -0x18(%ebp),%eax
0x004013d7 <_Z4testv+9>: mov %eax,(%esp)
0x004013da <_Z4testv+12>: call 0x4167a0 <_ZN8RAIITestD1Ev> //here destructor is called
0x004013df <_Z4testv+17>: mov $0x3,%eax //here result is pushed onto the stack
}
0x004013e4 <_Z4testv+22>: leave
0x004013e5 <_Z4testv+23>: ret
the compiler is gcc/g++ 3.4.5
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果对
this->_val
的访问是通过this->_mutex
同步的,那么您就无法选择当前编写代码的方式。在解锁互斥锁之前,您需要阅读this->_val
并且必须在返回之前解锁互斥锁。result
变量对于获取此操作顺序是必需的。如果您使用
lock_guard
(或 Boost 中的scoped_lock
),那么您不需要使用临时变量,因为当函数返回时,互斥体上的锁将被释放。例如,使用 C++0x 线程库:If access to
this->_val
is synchronized bythis->_mutex
, then you don't have a choice the way the code is written currently. You need to readthis->_val
before you unlock the mutex and you have to unlock the mutex before you return. Theresult
variable is necessary to get this order of actions.If you use a
lock_guard
(orscoped_lock
in Boost), then you don't need to use the temporary because the lock on the mutex will be released when the function returns. For example, using the C++0x threads library:是的,如果您使用显式的lock()/unlock()。如果您在堆栈上构造一个锁定对象并让其析构函数进行解锁,则不会。
Yes if you use explicit lock()/unlock(). No if you construct a lock object on the stack and have its destructor do the unlock.
否——编译器会自动为返回值创建一个临时值。通常也不需要使用互斥锁来保护读取,因此即使它是多线程的,只需
return _val;
就足够了。顺便说一句,我会去掉前导下划线——当变量名以下划线开头时可以使用和不能使用哪些变量名的规则足够复杂,最好完全避免它们。
No -- the compiler creates a temporary for the return value automatically. You don't normally need to protect a read with a mutex either, so even though its multithreaded, just
return _val;
should be sufficient.As an aside, I'd get rid of the leading underscore though -- the rules about what variable names you can and cannot use when they start with an underscore are sufficiently complex that it's better to just avoid them entirely.
您可以干净地做到这一点,因为您的互斥体被封装在一个在销毁时解锁的作用域锁中:
是的,您确实需要持有锁直到它返回。
You can do this cleanly is your mutex is encapsulated in a scoped_lock that unlocks on destruction:
And yes, you do need to hold the lock until it's returned.