gpt4 book ai didi

java - 读取和写入变量引用的线程安全性

转载 作者:行者123 更新时间:2023-12-02 02:39:07 25 4
gpt4 key购买 nike

我已阅读 Oracle's documentation ,其中指出(除其他外):

Reads and writes are atomic for reference variables

这意味着,假设我正确理解这一点,下面的代码是线程安全的,不需要 volatile 同步或使用 类,因为 otherHashlisthashlist 的实际赋值是原子的,并且从 hashlisttempHashlist 的赋值也是原子的原子。

public class SomeClass
{
private HashMap<Integer, ArrayList<MyObject>> hashlist = null;

// ...Thread/Runnable logic to periodically call set()...

private void set()
{
HashMap<Integer, ArrayList<MyObject>> otherHashlist = new HashMap<Integer, ArrayList<MyObject>>();

// ...populate otherHashlist...

hashlist = otherHashlist;
}

public ArrayList<MyObject> get(int i)
{
HashMap<Integer, ArrayList<MyObject>> tempHashlist = hashlist;

return new ArrayList<MyObject>(tempHashlist.get(i));
}
}

此外,在 get()set() 之外,绝不会以任何方式访问 hashlistset() 也不能被类外部的任何东西直接或间接调用。 get()返回的ArrayList是new,因此修改ArrayList的操作(set()、remove()等)不会影响中原来的ArrayList >哈希列表。我还没有在 MyObject 上定义任何 setter 方法,其所有成员变量都是 private final intprivate final long >私有(private)最终字符串

那么,我的问题是:这段代码实际上是线程安全的吗?或者我所做的一些假设/我遗漏的角度是否会使这变得不安全?

最佳答案

这不是线程安全的,因为虽然设置字段是安全的并且不会导致重叠更新,但其他线程实际上可能无法看到这些更改。也就是说,即使 Thread1hashlist 设置为某项,Thread2 也可能看不到该更改。这是因为 JVM 可以优化对 Thread2hashlist 的访问,例如将引用复制到寄存器中,这样就不需要执行 getfield 多次。在这种情况下,当Thread1更改hashlist时,Thread2看不到它,因为它不再使用该字段,而是使用一个它的本地副本,它认为字段。 This question展示了在这种情况下会发生什么。

最简单的做法是标记 hashlist volatile,这意味着一个线程中的更改实际上会被其他线程看到。

关于java - 读取和写入变量引用的线程安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45774269/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com