我有一个多线程类A,它访问另一个B类的以下insert()
方法(A只有一个B实例)。
有没有更好的方法来同步以下方法,而不是使整个方法同步? (减少同步开销)
private void insert(byte[] shardKey, byte[] queueKey,
byte[] value, PipelineMessageType msgType) {
PipelineMessage pipelineMessage = new PipelineMessage(queueKey,
value, msgType);
LinkedBlockingQueue<PipelineMessage> queue;
JedisShardInfo shardInfo = shardedJedis.getShardInfo(shardKey); // shardedJedis is an instance variable of this class
String mapKey = shardInfo.getHost() + shardInfo.getPort();
queue = shardQueue.get(mapKey); // shardQueue is an instance variable of this class
boolean insertSuccessful = queue.offer(pipelineMessage);
if(!insertSuccessful) {
// perform the pipeline sync - flush the queue
// use another thread for this
// (processing of queue entries is given to another thread here)
// queue would be empty now. Insert (k,v)
queue.offer(pipelineMessage);
}
}
我尝试仅同步访问实例变量的片段,但可能存在2个线程尝试插入完整队列并输入if
块的情况。然后2个线程可能会处理我不想发生的队列条目。
任何建议都表示赞赏。先感谢您。
答案 0 :(得分:1)
对我来说,如果JedisShardInfo是一个只读项,那么你应该保护/同步它。因此,您只能从行
进行同步queue= ...
否则,除了第一个语句(管道消息的声明)之外,几乎所有内容都应该同步,然后我真的不知道与声明整个方法同步相比它是否会发生很大变化。
另外,如果你有其他的同步点,我指的是在这个上同步的其他方法或块代码,你应该考虑拆分它们并根据你想要保护的多个数据成员同步它们的不同数据成员 - 线程:
Object lockerA = new Object() {};
synchronized( lockerA )
{}//sync
好吧,不多说。 :)
此致 斯特凡
答案 1 :(得分:1)
纠正同步的关键是遵循以下模式:
synchronize(lockObjectForState) { // All code that alters state must also synchronise on the same lock
while(!stateOkToProceed()) {
try {
lockForState.wait();
} catch (InterruptedException e) {
// handle if your thread was interrupted deliberately as a single to exit, or spuriously (in which case do nothing)
}
}
updateState();
lockForState.notifyAll();
}
java.util.concurrent
包提供了许多解决常见线程问题所需的类的线程安全实现。考虑使用BlockingQueue。