创建类线程安全性的简单方法是添加一个互斥体属性并将互斥锁锁定在访问器方法中
class cMyClass { boost::mutex myMutex; cSomeClass A; public: cSomeClass getA() { boost::mutex::scoped_lock lock( myMutex ); return A; } };
问题是这使得类不可复制.
通过使互斥锁静态,我可以使事情发挥作用.但是,这意味着当访问任何其他实例时,该类的每个实例都会阻塞,因为它们都共享相同的互斥体.
我想知道是否有更好的方法?
我的结论是没有更好的办法.使用私有静态互斥体属性使线程安全的是“最好的”: – 它很简单,它的工作原理,它隐藏了尴尬的细节.
class cMyClass { static boost::mutex myMutex; cSomeClass A; public: cSomeClass getA() { boost::mutex::scoped_lock lock( myMutex ); return A; } };
缺点是类的所有实例共享相同的互斥体,因此不必要地彼此阻止.这不能通过使互斥体属性非静态(因此给予每个实例自己的互斥体)来解决,因为复制和分配的复杂性是噩梦,如果正确的话.
如果需要,个人互斥体必须由外部不可复制的单例管理,并在创建时为每个实例建立链接.
感谢所有回应.
有几个人已经提到编写我自己的拷贝构造函数和赋值操作符.我试过了问题在于,我的真实类有许多属性,在开发过程中总是会发生变化.维护复制构造函数和assignmet操作符是乏味且容易出错的,错误创建难以找到错误.让编译器为复杂类生成这些是一个巨大的节省时间和减少错误.
许多响应都关注使拷贝构造函数和赋值操作符线程安全.这个要求给整个事情增加了更多的复杂性!幸运的是,我不需要它,因为所有的复制都是在一个单独的线程中完成的.
我现在认为最好的办法是建立一个很小的类来保存互斥体和关键属性.然后我可以为关键类编写一个小的复制构造函数和赋值运算符,并保留编译器来监视主类中的所有其他属性.
class cSafe { boost::mutex myMutex; cSomeClass A; public: cSomeClass getA() { boost::mutex::scoped_lock lock( myMutex ); return A; } (copy constructor) (assignment op ) }; class cMyClass { cSafe S; ( ... other attributes ... ) public: cSomeClass getA() { return S.getA(); } };
解决方法
简单的事实是,您不能通过在问题上暴露互斥体来使得线程安全.你不能做这个工作的原因是因为它不起作用,而不是因为你这样做错了.这是大家注意到,当多线程第一次来,并开始屠宰COW字符串实现.
线程设计发生在应用程序级,而不是基于每个类.只有具体的资源管理类才能在这个级别上具有线程安全性,对于他们,您需要编写显式的复制构造函数/赋值操作符.