Pseudocode:
Function1_vector_copy () {
vectora = vectorb;
}
Function2_vector_search() {
find k in vectora;
}
该程序是多线程的。虽然许多线程可能会搜索,但矢量复制只能由单个线程完成,但偶尔会进行。问题是它可能是什么,vector_search不应该失败。 Vector_copy可以延迟,但vector_search不应该延迟。它没有延迟,没有失败模式。问题是共享变量vectora必须是持久的,因此vector_search根本不会失败。实现这一目标的最佳方式是什么?
编辑:
Using an answer for another question
boost::shared_mutex _access;
Function1_vector_copy() {
// get upgradable access
boost::upgrade_lock lock(_access);
// get exclusive access
boost::upgrade_to_unique_lock uniqueLock(lock);
// now we have exclusive access
vectora.swap(vectorb);
}
Function2_vector_search() {
// get shared access
boost::shared_lock lock(_access);
// now we have shared access
find k in vectora ;
}
如果具有可升级所有权的线程尝试升级而其他线程升级 线程有共享所有权,尝试将失败并且线程 将阻止,直到获得独家所有权。 --boost-documentation
技巧是矢量复制是异步完成的,它将在获得独占所有权后发生。因此,矢量副本最终会发生但延迟,实际上矢量副本也是一个非故障操作但延迟了,这对我来说是可以的。将以某种方式锁定同步,我们将阻止至少毫秒。但是使用这种交换的优势将导致更短的时间,使其可以忽略不计。
答案 0 :(得分:2)
Function1_vector_copy ()
{
VectorType tmp = vectorb;
rwLock.acquireWrite();
swap(tmp,vectora);
rwLock.releaseWrite();
}
其余部分留给读者练习。
更新:总结以下评论......
首先,我应该明确上面的原始swap(...)
调用是伪代码,不一定是字面意思。我不知道究竟是什么VectorType
(技术上仍然没有)。我假设您打算尽可能高效地进行swap()。毕竟这是伪代码......
在任何情况下,std::swap()
都专门用于C ++标准库中的所有容器类型。因此,如果VectorType
实际上是std::vector<UDT>
,则swap(tmp,vectora);
应该是最优的并且无需修改即可工作(依靠Koenig查找来解析符号)。
答案 1 :(得分:2)
我认为mcmcc的想法并不太远,但是通用的std :: swap()将执行向量复制,你应该能够使用std :: vector :: swap()。功能向量的交换功能与通用功能相同,但速度要快得多,因为它只是交换了少量指针/大小变量而实际上并没有进行元素复制。所以你的锁只能用于少量装配说明。
如果那仍然太长(此时你可能想要检查你的设计),另一种选择是拥有一个永远不会相互替换的矢量循环列表。而是有另一个引用“活动”向量的指针。当您需要修改该集合时,初始化圆圈中的下一个向量,并在初始化完成后更新指针。有了这个解决方案,根本就没有锁。读者使用一个向量的瞬间,下一瞬间他们使用不同的向量。
第二个解决方案的缺点是它肯定需要更多内存,而且有点不可预测。我想你可以声明你的“活动”向量指针 volatile ,这会强制CPU确保每次读取指针值时都会同步缓存,否则,有一些非确定性元素,其中多个CPU核心可能正在看主存的不同快照。也没有任何同步,你如何确保其他线程完成与即将被吹走的向量?如果你进行任何类型的同步,你就会恢复RW锁定。
虽然我认为你可以得到第二种工作方式,并且可以相对稳定地进行一些调整......我的第一直觉是使用RW lock和vector :: swap()。
更新:实际上,我只是重新阅读规范,看起来STL专门为容器设计了全局std :: swap,包括std :: vector。所以即使在调用全局函数时,复杂度也是O(1)。 mcmcc的答案有效。
所以我们把这个猜测放在一边,我只是写了一些代码并用调试器逐步完成。这是我的应用程序代码:
std::vector< int > a, b;
for( int i = 0; i < 10; i++ )
{
a.push_back( i );
b.push_back( i * 10 );
}
std::swap( a, b );
这里是对std :: swap的全局通用版本的调用内容:
template<class _Ty,
class _Alloc> inline
void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right)
{ // swap _Left and _Right vectors
_Left.swap(_Right);
}
正如你所看到的,通用std :: swap模板函数,它在泛型模式中的复制构造函数,专门用于向量。在内部,它只是将所有工作委托给std :: vector :: swap(),我们建立的是一个更快的变体。