为了账号安全,请及时绑定邮箱和手机立即绑定

在 Java 中重新分配列表是否是线程安全的?

在 Java 中重新分配列表是否是线程安全的?

牧羊人nacy 2022-06-15 10:49:10
我正在使用在 ArrayList 上运行的两个线程。我知道您不能在迭代时修改列表,但 Java 让我在循环中重新分配(替换)整个列表,没有问题。这是线程安全的吗?public class Main {    static List<String> list = Arrays.asList("hi", "there", "friend");    public static void main(String... args) throws InterruptedException {        boolean isReassigned = false;        for (String s: list) {            System.out.println(s);            if (!isReassigned) {                new Thread(() -> reassignList()).start();                isReassigned = true;            }            Thread.sleep(1000);        }    }    public static void reassignList() {        System.out.println("Reassigning list....");        list = Arrays.asList("goodbye", "old", "list");    }}我预计在“嗨”之后会出现并发问题,但我得到了“嗨,朋友”。我认为这是可行的,因为 Java 在引用上按值复制,但我担心我的生产应用程序每 1 分钟重新分配一次数组可能有一天会爆炸。感谢大家!
查看完整描述

1 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

您看不到更新的列表内容,因为增强的 for循环在幕后使用了迭代器。因此,您正在使用迭代器(到旧列表)来迭代数据(即使在分配完成之后)。这意味着这两个列表都在范围内(而不是垃圾收集)。一次,isReassigned是的,如果你得到一个迭代器,list你就可以看到新的内容。


我已经稍微更改了您的代码(添加了一个else块)以理解这一点


for (String s: list) {

    System.out.println(s);

    if (!isReassigned) {

        new Thread(() -> reassignList()).start();

        isReassigned = true;

    } else {

        System.out.println("Latest data " + list);

    }

    Thread.sleep(1000);

 }

这产生


hi

Reassigning list....

there

Latest data [goodbye, old, list]

friend

Latest data [goodbye, old, list]

其他几点:

  1. 您不应该isReassigned从主线程进行设置。必须在分配列表后设置。

  2. 正如@Kartik 在评论中指出的那样,可能存在可见性问题,其他线程可能看不到所做的更改。标记列表 isReassigned 和易失性将解决这个问题。


查看完整回答
反对 回复 2022-06-15
  • 1 回答
  • 0 关注
  • 98 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信