const
(指针,引用和成员函数)如何帮助C ++中的线程安全?
答案 0 :(得分:14)
任何不可变(即不可变)的数据本质上都是线程安全的 - 多个线程同时读取相同的只读数据没有风险,因为它永远不会改变!
在C ++中将变量标记为const使其成为只读,从而使线程安全。
答案 1 :(得分:6)
多线程的主要问题是可变性。 const限制了这一点,但既然你可以抛弃常量,那就不是万无一失的。
答案 2 :(得分:6)
const成员函数不应该改变状态,这样可以安全地同时从多个线程调用。但是线程安全不是const的目的,C ++提供了mutable关键字和const_cast,这意味着const实际上并不保证线程安全,不应该依赖它。
答案 3 :(得分:4)
Const函数不是线程安全的。 Normaly,你可以同时从不同的线程调用const对象方法,但如果从不同的线程调用非const和const方法,你就会遇到竞争条件。检查一下:
class Foo
{
size_t size_;
public:
...
size_t get_size() const
{
return size_
}
};
class Bar
{
boost::shared_ptr<Foo> foo_;
public:
//accessor
size_t get_size() const
{
size_t size = 0;
if (foo_)
size = foo_->size();
return size;
}
//modifiers
void init()
{
foo_ = new Foo;
}
void clear()
{
foo_ = boost::shared_ptr<Foo>();
}
};
如果有人调用init方法,然后同时调用clear和get_size方法,则会导致访问冲突。您必须使用读写锁定习语。可以同时调用多个访问器,并且只能同时调用一个修改器。 例:
class Bar
{
boost::shared_ptr<Foo> foo_;
mutable tbb::spin_rw_mutex lock_;
public:
//accessor
size_t get_size() const
{
size_t size = 0;
//lock modifiers
rw_mutex_type::scoped_lock lock(mutex, false);
if (foo_)
size = foo_->size();
return size;
}
//modifiers
void init()
{
//lock accessor and modifiers
rw_mutex_type::scoped_lock lock(mutex, true);
foo_ = new Foo;
}
void clear()
{
//lock accessor and modifiers
rw_mutex_type::scoped_lock lock(mutex, true);
foo_ = boost::shared_ptr<Foo>();
}
};
tbb :: spin_rw_lock是来自threading builing blocks library
的互斥类答案 4 :(得分:4)
C ++ const允许非常量别名,例如:
Foo myVar;
const Foo* ptr1;
Foo* ptr2;
鉴于此,const不保证数据的不变性,即使您没有进行任何转换或任何事情来绕过它。如果您通过ptr1访问myVar,则无法通过ptr1更改它(假设我的语法正确;这就是意图。)但是,它仍然可以通过ptr2进行更改。你真正想要的是一个单独的不可变构造。这在C ++中不存在。
答案 5 :(得分:3)
Const和线程安全是正交概念。
以const函数为例:一个类可能同时具有const和非const函数,并且一个线程可能正在调用一个非const函数,该函数在另一个线程处于其const函数的同时修改该对象。在这种情况下,标记功能const不会提供任何安全性。只有使用锁定或其他同步原语才能实现线程安全。