[英]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.