我在主题1中有以下代码:
synchronized (queues.get(currentQueue)) { //line 1
queues.get(currentQueue).add(networkEvent); //line 2
}
以及主题2中的以下内容:
synchronized (queues.get(currentQueue)) {
if (queues.get(currentQueue).size() > 10) {
currentQueue = 1;
}
}
现在我的问题:currentQueue变量当前的值为0.当线程2将currentQueue的值更改为1并且线程1在第1行等待(因为已同步)时,线程1是否使用更新的currentQueue线程2完成后第2行的值(这就是我想要的)。
答案 0 :(得分:2)
您问题的正确答案是:结果未定义。
您的监视器对象是queues.get(currentQueue),但由于currentQueue是可变的,因此您的监视器是可变的,因此它当前所处的状态或多或少是随机的。实际上,这段代码最终会破裂。
修复它的一种简单方法是这样的函数:
protected synchronized QueueType getCurrentQueue() {
return queues.get(currentQueue);
}
然而,这仍然是实施整个事情的坏方法。您应该尝试通过使用并发队列(如ConcurrentLinkedQueue)或使用锁定/最终监视器对象来完全消除同步。
final Object queueLock = new Object();
...
synchronized(queueLock) {
queues.get(currentQueue).add(networkEvent);
}
请注意,每次访问queues
或currentQueue
时都必须使用该锁定,因为两者都定义了您正在使用的数据集。
答案 1 :(得分:2)
这个问题的答案取决于它。我假设有其他代码块增加currentQueue变量。在这种情况下,锁定不会发生在' currentQueue '变量,它不会发生在' 队列'的集合中,而是发生在&#39中的10个队列之一(或者你有多少个) ; 队列'集合。
因此,如果两个线程碰巧访问同一个队列(比如队列5),那么你的问题的答案是肯定的。但是,为了实现这一点,十分之一的机会(一个x机会,其中x =' 队列'集合中的数字或队列)。因此,如果线程访问不同的队列,那么答案是否定的。
答案 2 :(得分:1)
假设你没有其他线程会改变currentQueue的值,是的,线程1将最终使用更新的 currentQueue 值所指向的队列,因为你正在调用queues.get( currentQueue)再次在synchronized块的主体中。但这并不意味着您的同步是合理的。实际上你应该在currentQueue上同步,因为它似乎是访问当前队列的共享密钥。
还要记住,当您使用同步时,您正在同步变量的引用,而不是它的值。因此,如果您将新对象重新分配给它,那么您的同步就不再有意义了。