我需要几个STL容器,线程安全。
基本上我认为我只需要为每个STL容器对象添加2个方法,
.lock()
.unlock()
我也可以将其分解为
.lockForReading()
.unlockForReading()
.lockForWriting()
.unlockForWriting()
可行的方法是可以接受任意数量的并行读取锁,但如果有写入锁,则会阻止读取和写入。
尝试锁定写入等待直到lockForReading信号量降为0。
有没有一种标准方法可以做到这一点?
我是如何计划做错的或短视的?
答案 0 :(得分:6)
执行此操作的标准方法是获取构造函数中的锁,并在析构函数中释放它。这通常称为资源获取初始化或RAII。我强烈建议你使用这种方法而不是
.lock()
.unlock()
这不是例外安全。您可以在投掷之前轻易忘记解锁互斥锁,从而在下次尝试锁定时导致死锁。
Boost.Thread库中有几种同步类型对您有用,notably boost::mutex::scoped_lock.
而不是将lock()
和unlock()
方法添加到任何容器中希望从多个线程访问,我建议您使用boost:mutex
或等效的,并在访问容器时实例化boost::mutex::scoped_lock
。
答案 1 :(得分:6)
这真的很糟糕。外部代码无法识别或理解您的线程语义,容器中对象的别名易用性使它们成为可靠的线程安全接口。
线程安全发生在设计时间。你不能通过在问题上抛出锁来解决线程安全问题。通过不让两个线程同时写入相同的数据来解决线程安全问题 - 当然,在一般情况下。但是,除了直接线程同步原语之外,不是处理线程安全的特定对象的责任。
你可以拥有并发容器,旨在允许并发使用。但是,它们的接口与标准容器提供的接口差不多。例如,容器中对象的别名较少,并且每个单独的操作都被封装。
答案 2 :(得分:2)
有没有一种标准方法可以做到这一点?
不,这是有原因的。
我是如何计划这样做的 错误或短视?
想要同步对单个容器对象的访问并不一定是错的,但是容器类的接口 通常是放置同步的错误位置(like DeadMG says:object别名等。)。
就我个人而言,我认为TBB和concurrent_vector这样的内容可能是过度杀戮,或者仍然是“简单”同步问题的错误工具。
我发现,有时只是添加一个(私有)Lock对象(到容纳容器的类),并将2或3个访问模式包装到一个容器对象就足够了,并且对于其他人来说将更容易掌握和维护在路上。
答案 3 :(得分:-1)
Sam:您不希望使用.lock()
方法,因为某些内容可能会出错,导致阻止在阻止结束时调用.unlock()
方法,但如果.unlock()
被称为堆栈分配变量的对象破坏的结果,然后从调用.lock()
的函数的任何类型的早期返回将被保证释放锁。
DeadMG: 英特尔的Threading Building Blocks(open source)可能正是您所寻找的。 p>
还有Microsoft's concurrent_vector and concurrent_queue,Visual Studio 2010已经附带。