我正在开发一个软件,其中多个线程读取访问具有大量数据(大数据)的单个<collection xmlns="http://exist-db.org/collection-config/1.0">
<triggers>
<trigger class="org.exist.jms.replication.publish.ReplicationTrigger">
<!--
Class name of the initial context provider, default value
for ActiveMQ
see javax.naming.Context#INITIAL_CONTEXT_FACTORY
-->
<parameter name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
<!--
URL of the message broker, default value for ActiveMQ
see javax.naming.Context#PROVIDER_URL
-->
<parameter name="java.naming.provider.url" value="tcp://localhost:61616"/>
<!--
Lookup connection factory
see javax.naming.InitialContext#lookup(String)
-->
<parameter name="connection-factory" value="ConnectionFactory"/>
<!--
Lookup destination (topic)
see javax.naming.InitialContext#lookup(String)
-->
<parameter name="destination" value="dynamicTopics/eXistdb-replication-example"/>
</trigger>
<trigger event="update" class="org.exist.collections.triggers.XQueryTrigger">
<parameter name="url" value="xmldb:exist:///db/triggerUpdate.xql"/>
</trigger>
</triggers>
</collection>
。
我对访问单个对象的多个主题的复杂性有一些基本的了解,使用互斥锁可以大大简化事情。
就我而言,修改现有对象比复制它要昂贵得多。所以我在考虑创建一个副本,修改该副本(不持有互斥锁),然后 然后将其交换回共享对象。
我无法使用C ++ 11,因此我无权进行移动操作,但是据我了解,std::vector
使用了非常有效的gcc
与移动操作相当(在速度)。
我在想这样的事情:
std::vector::swap()
pthread_mutex_t mtx;
class bigdata_t { ... };
std::vector<bigdata_t> shared_vec; // accessed by multiple threads
void modify_bigdata()
{
pthread_mutex_lock(&mtx);
std::vector<bigdata_t> tmp_vec = shared_vec; // create copy
pthread_mutex_unlock(&mtx);
/*
* Here, apply expensive modifications to tmp_vec
*/
pthread_mutex_lock(&mtx);
shared_vec.swap(tmp_vec); // this is very fast and does not copy data
pthread_mutex_unlock(&mtx);
}
仅由单个线程调用,因此,这基本上是单个编写器/多个读取器的方法。
它运行速度非常快,但是将数据交换回共享矢量中的感觉就像作弊。
我的问题是:
这种方法正确且线程安全吗?
答案 0 :(得分:1)
假设您交换了整个向量,那么当任何读取器线程在该向量中具有引用时,就像在交换时那样,这是非常危险的,另一个向量很可能被破坏,在这种情况下,来自读取器线程的任何引用都可能变为无效。
因此,每次您的阅读器线程访问该向量时,它们都将需要一个锁。因此,使用swap在这里无济于事。唯一可行的方法是通过使用某种多读取器-单写入器锁来确保没有读取器处于活动状态。
最适合您的是
std::vector<std::shared_ptr<bigdata_t>> shared_vec;
这样,您只需要正确同步指针的交换并确保: