繁体   English   中英

Java线程安全性和原语

[英]Java thread safety and primitives

我有一个包含一些原始变量的对象

public class Myobject {
    public final double d
    public long a
}

我将所有这些对象存储在不同步的集中

private Set<Myobject> myset = new HashSet<>()

现在我想将这些对象传递到另一个线程并执行一些计算。 在这个线程中,我只会读取变量“ d”和“ a”,变量不会被更改。我的问题是,如果线程安全地创建一个不可修改的集合,Collections.unmodifiableset(myset); 并将其传递给第二个线程。

您有两个基本选项可以安全地发布对对象图根的引用:

  • 确保构造对象图的线程是启动(全部)将使用它的子线程的线程;

  • 将对完全构造的对象图的引用写到volatile变量。

两种方法都确保在构造对象图时执行的所有线程间store操作与其他线程将针对同一图执行的所有线程间load操作之间的事前关联。 由于保证第一个线程间操作是load (读取根引用),因此这也意味着另一个线程的所有store操作都在发生之前 因此,在另一个线程中读写对象都是线程安全的-只要它是另一个线程,而不是另一个线程

作为标准的预防措施,我在JLS§17.4.4中包括以下引号:

  • 对易失性变量v写操作(第8.3.1.4节) 任何线程对v的所有后续读取进行同步 (其中“后续”是根据同步顺序定义的)。

  • 启动线程的动作与它启动的线程中的第一个动作同步。

不,创建无法修改的集合是不够的。 您必须确保构造(和/或修改)对象的线程将对象安全地发布到读取该对象的线程。 有几种方法可以做到这一点。 其中有些很难正确。 最正确的解决方法是拥有一个锁对象 ,并在写入,构造读取该锁时使机器人线程在该锁上进行同步。

如果我对您的理解正确,那么您甚至不需要为线程安全创建一个不可修改的集合。

如果您在一个线程中创建集合,然后将其传递给另一个线程以执行某些操作,而又不从第一个线程访问它,那么就不会发生线程冲突,因为一次最多可以有一个主题你的设置。

暂无
暂无

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

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