class Manager {
public:
list<Employee> getEmployees() {
// Do I need to lock here?
return emps_;
}
void addEmp(Employee emp); //Here I have lock
private:
list<Employee> emps_;
};
实例Manager
在多个线程之间共享。
我需要添加锁吗getEmployees
会员功能?
我非常确定我需要锁,因为完整的列表已被复制,因此在此期间(直到复制完成)进行的任何修改都可能会破坏复制操作。
我只是问这个问题,因为我很少有人认为不需要锁定。
Edit:
既然现在很清楚需要 lock ,我的问题是如何以最小的开销来做到这一点。
通过执行以下解决方案,您可以将列表复制两次:
list<Employee> getEmployees() {
pthread_mutex_lock( &mutex1 );
list<Emp> tmp = emps_; //Copy 1
pthread_mutex_unlock( &mutex1 );
return tmp;//Copy 2
}
整个列表被复制,但副本的源可能正在修改。 stdlib 容器支持完全并发的未锁定读取访问。另一方面写...
如果您要在可能进行复制时写入此列表,则需要将其锁定。顺便说一句,SWMR(单写入多读取)锁非常适合这种情况,特别是如果您有数十甚至数百个线程需要制作副本,而只需要偶尔写入。即便如此,编写者请求的匮乏是一个需要通过锁定类的实现来解决的真正问题,但不适用于您此处问题的范围(没有双关语)。
关于您的更新,我是适当时范围释放锁的忠实粉丝,在您的情况下也是如此。 IE。围绕互斥体的作用域对象包装器,在进入时锁定它,并在作用域退出时解锁它。
我非常确定 boost:: 人们可以轻松获得这样的东西,就这一点而言,C++11 也可能如此(由于工作安排,我还没有采取这种措施;没有停机时间啊)。但你想要这样的东西:
list<Employee> getEmployees()
{
scope_lock latch(&mtx);
return emps_;
}
The scope_lock
上面只是一个简单的类,它在构造时锁定互斥锁,并在销毁时解锁它。这可以防止复制构造中抛出的异常不会永久挂起互斥体的可能性。将其视为利用自动破坏来解锁互斥锁。RAII http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization为了胜利。
我希望这是有道理的。对于像这样的小人物来说,这样的东西是理想的。再说一次,包括 boost 在内的许多工具包可能都内置了这样的东西,如果任何 boost 人员读到了这篇文章,请牛仔起来并指点一下。上面的示例是您所能得到的最简单的作用域锁。
最后,对于 SWMR,逻辑完全相同。唯一的区别是锁将需要一个额外的参数来确定您是否请求读或写访问权限。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)