Java 如果LinkedList被大量线程快速添加/删除,对象会丢失吗?

Java 如果LinkedList被大量线程快速添加/删除,对象会丢失吗?,java,multithreading,concurrency,Java,Multithreading,Concurrency,听起来像个愚蠢的问题。我刚开始使用Java并发 我有一个LinkedList,它充当任务队列,由多个线程访问。它们移除并执行first(),其他线程则放置更多任务(.add())。任务可以让线程将它们放回队列 我注意到,当有很多任务并且它们被大量放回队列中时,我最初添加到队列中的任务数量并不是原来的数量,1,有时2缺失 我检查了所有内容,并同步了每个关键部分+notifyAll() 已将LinkedList标记为“volatile” 确切的数字是384个任务,每个任务被放回3072次 如果有少量

听起来像个愚蠢的问题。我刚开始使用Java并发

我有一个LinkedList,它充当任务队列,由多个线程访问。它们移除并执行first(),其他线程则放置更多任务(.add())。任务可以让线程将它们放回队列

我注意到,当有很多任务并且它们被大量放回队列中时,我最初添加到队列中的任务数量并不是原来的数量,1,有时2缺失

我检查了所有内容,并同步了每个关键部分+notifyAll()

已将LinkedList标记为“volatile”

确切的数字是384个任务,每个任务被放回3072次

如果有少量的任务&返回,则不会出现问题。另外,如果我完成了System.out.println()所有步骤,那么它就不会再发生了,因此我无法调试

是否有可能LinkedList.add()不够快,因此线程不知何故错过了它

简化代码:

public void callByAllThreads() {     
      Task executedTask = null;
      do 
      {
        // access by multiple thread
      synchronized(asyncQueue) {
          executedTask = asyncQueue.poll();
          if(executedTask == null) {
          inProcessCount.incrementAndGet(); // mark that there is some processing going on
        } 
      }

      if(executedTask != null) {
        executedTask.callMethod(); // subclass of task can override this method
        synchronized(asyncQueue) {
          inProcessCount.decrementAndGet();
          asyncQueue.notifyAll();
        }
      }
      }
      while(executedTask != null);
}
该任务可以覆盖callMethod:

public void callMethodOverride() {
  synchronized(getAsyncQueue()) {
    getAsyncQueue().add(this);
    getAsyncQueue().notifyAll();
  }
}

LinkedList
绝对不是线程安全的;您无法在多线程中安全地使用它。这不是“足够快”的问题,而是一个线程所做的更改对其他线程可见的问题。将其标记为volatile无济于事;这只会影响对正在更改的
LinkedList
的引用,而不会影响对
LinkedList
内容的更改


考虑
ConcurrentLinkedQueue
ConcurrentLinkedQueue

LinkedList
绝对不是线程安全的;您无法在多线程中安全地使用它。这不是“足够快”的问题,而是一个线程所做的更改对其他线程可见的问题。将其标记为volatile无济于事;这只会影响对正在更改的
LinkedList
的引用,而不会影响对
LinkedList
内容的更改

考虑
ConcurrentLinkedQueue
ConcurrentLinkedQueue

来自:

请注意,此实现是不同步的。如果多个线程同时访问一个链表,并且至少有一个线程在结构上修改链表,则必须在外部对其进行同步

i、 e.您应该同步访问列表。您说您是,但如果您看到项目“丢失”,那么您可能没有正确同步。您可以使用一个框架类来完成它,而不是尝试这样做

。。。如果您总是删除下一个可用(第一个)项(实际上是生产者/消费者实现),那么您可以使用一个实现,这保证是线程安全的,并且具有在一个项可用之前阻止消费者的优点。例如
ArrayBlockingQueue

对于非阻塞线程安全队列,您可以查看

标记列表实例变量
volatile
与您的列表是否同步以进行变异方法(如
add
removeFirst
)无关
volatile
只是为了确保该实例变量的读/写在线程之间正确通信,并在线程内正确排序。请注意,我说的是该变量,而不是该变量的内容(请参见)

来源:

请注意,此实现是不同步的。如果多个线程同时访问一个链表,并且至少有一个线程在结构上修改链表,则必须在外部对其进行同步

i、 e.您应该同步访问列表。您说您是,但如果您看到项目“丢失”,那么您可能没有正确同步。您可以使用一个框架类来完成它,而不是尝试这样做

。。。如果您总是删除下一个可用(第一个)项(实际上是生产者/消费者实现),那么您可以使用一个实现,这保证是线程安全的,并且具有在一个项可用之前阻止消费者的优点。例如
ArrayBlockingQueue

对于非阻塞线程安全队列,您可以查看


标记列表实例变量
volatile
与您的列表是否同步以进行变异方法(如
add
removeFirst
)无关
volatile
只是为了确保该实例变量的读/写在线程之间正确通信,并在线程内正确排序。请注意,我说过变量,而不是该变量的内容(请参阅)

LinkedList不是线程安全的,因此,是的,多个线程同时访问它会导致问题。同步关键部分可以解决这个问题,但由于您仍然存在问题,您可能在某些地方犯了错误。尝试将其包装到集合中。synchronizedList()以同步所有方法调用。

LinkedList不是线程安全的,因此是的,多个线程同时访问它会导致问题。同步关键部分可以解决这个问题,但由于您仍然存在问题,您可能在某些地方犯了错误。尝试将其包装到集合中。synchronizedList()以同步所有方法调用。

链表是线程安全的,如果它适合您的需要,您可以使用它,这似乎是可能的

正如文件所说

基于链接节点的无限线程安全队列。这个队列 订单元素FIFO(先进先出)。队列的头是 在队列中停留时间最长的元素。尾巴 队列是队列中最短的元素 时间在队列的尾部插入新元素,然后 队列检索操作获取队列头部的元素。A. 当许多线程需要时,ConcurrentLinkedQueue是一个合适的选择 分享