繁体   English   中英

两个线程同时访问同一ArrayList?

[英]Two threads accessing the same ArrayList at the same time?

我在线程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(这就是我想要的)。

您问题的正确答案是:结果不确定。

您的监视器对象是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);
}

请注意,每次访问queuescurrentQueue都定义要使用的数据集时,必须使用该锁定。

问题的答案在于它取决于。 我假设还有其他代码块可以增加currentQueue变量。 在这种情况下,锁定不会发生在' currentQueue '变量上,也不会发生在' queue '的集合上,而是发生在'10个队列中的10个(或者有很多)队列中的一个上。 队列收集。

因此,如果两个线程碰巧都访问同一个队列(例如队列5),那么您问题的答案是肯定的。 但是,发生这种情况的机会是十分之一(x机会是1,x =“ queues ”集合中的队列数 )。 因此,如果线程访问不同的队列,那么答案是否定的。

假设您没有其他线程会更改currentQueue的值,那么是的,线程1最终将使用currentcurrent的更新值指向的队列结束,因为您在同步的正文中再次调用了queues.get(currentQueue)块。 但是,这并不意味着您的同步是正确的。 实际上,您应该在currentQueue上进行同步,因为它似乎是访问当前队列的共享密钥。

还要记住,当您使用sync时,您是在变量的引用而不是其值上进行同步。 因此,如果将新对象重新分配给它,则同步不再有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM