【问题标题】:How to make two threads take turns in modifying an arraylist?如何让两个线程轮流修改一个arraylist?
【发布时间】:2015-02-24 14:34:11
【问题描述】:

您将在下面看到的代码试图实现以下目标:

  • 将“第 0 行”添加到数组列表中
  • 打印数组列表中的最后一项,即“第 0 行”
  • 从数组列表中删除最后一项

  • 将“第 1 行”添加到数组列表中

  • 打印数组列表中的最后一项,即“第 1 行” 从数组列表中删除最后一项

...等等没有尽头。

所以,我期望的输出很简单:

第 0 行

第 1 行

..

..

但是,我得到的是随机数量的“i 行”,其中 i 也是随机的。 这是一个示例输出:

第 0 行

第 38919 行

第 47726 行

第 54271 行

然后程序陷入似乎是死锁的状态,即使这没有意义,因为变量 'held' 只能是真或假,并且任何一种情况都应该允许其中一个线程执行工作。

import java.util.*;

public class Test {

     static boolean held = true;
     static ArrayList<String> line = new ArrayList<>();


     public static void main(String[] args) {

        new Thread() {
            @Override
            public void run() {
                int i = 0;
                while(true) {
                    if(held) {
                        line.add("Line " + i);
                        i++;
                        held = false;
                    }
                }
            }


        }.start();

        while(true) {
            if(!held) {
                System.out.println( line.get(line.size() - 1) );
                line.remove(line.size() - 1);
                held = true;

            }else continue;
        }

    }


}

【问题讨论】:

  • 我在ideone上运行了这个,输出如你所愿。所以这一定是一些平台相关的问题。尝试将volatile 添加到持有的变量中。
  • 您可以尝试使用Semaphore
  • @Martijn Courteaux 让 'held' volatile 成功了,谢谢!
  • @VGR“允许编译器重新排序任一线程中的指令,只要这不影响单独执行该线程” - 现在解释了我的程序的行为,谢谢!跨度>

标签: java multithreading arraylist


【解决方案1】:

您可以使用两个线程同步的锁定对象,然后让每个线程在列表上执行它们的操作,然后使用等待和通知交替唤醒也执行相同操作的另一个线程。

【讨论】:

    【解决方案2】:

    您的held 变量不是volatile 可能会导致死锁。您计算机上的不同内核将拥有自己的内存缓存,这些缓存不一定会同时更新。为了确保所有线程都可以看到对 hold 的更改,您应该将其设为 volatile。您还可以使用 AtomicBoolean,或同步访问代码块。

    【讨论】:

      【解决方案3】:

      我认为对于这种情况,最好使用 synchronized list 而不是 arraylist:

      List line = Collections.synchronizedList(new ArrayList(...));
      

      【讨论】:

        【解决方案4】:

        第一件事是,在您的主线程中,您创建了两个不同的线程,第一个线程(子线程)和将处理主线程的 while 循环的主线程。这意味着您同时运行它们,因此当每个线程都在使用它时,您无法确定 held 的值是多少。要解决这个问题,您必须使用信号量或互斥量来访问 hold 进行更改。

        第二件事是,在您的 while 循环中,没有任何东西可以使程序脱离它们,这就是为什么它可能会导致您陷入无限循环。

        【讨论】:

          猜你喜欢
          • 2020-07-26
          • 1970-01-01
          • 1970-01-01
          • 2013-10-20
          • 2017-03-12
          • 1970-01-01
          • 2015-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多