Java 易变变量的突变对所有线程都可见吗?

Java 易变变量的突变对所有线程都可见吗?,java,multithreading,volatile,Java,Multithreading,Volatile,假设我有一个对MyClass的易失性引用c,MyClass有一个整数字段x。如果一个线程更改了x的值,那么新值是否保证对所有其他线程可见,或者x是否也必须是可变的 换句话说,下面的示例是否保证打印2 public class MyClass { private static volatile MyClass c; private int x = 1; public static void main(String[] args) { c = new MyClass(); Th

假设我有一个对MyClass的易失性引用c,MyClass有一个整数字段x。如果一个线程更改了x的值,那么新值是否保证对所有其他线程可见,或者x是否也必须是可变的

换句话说,下面的示例是否保证打印2

public class MyClass {

private static volatile MyClass c;

private int x = 1;

public static void main(String[] args) {
    c = new MyClass();
    Thread thread = new Thread(new Runnable() {

        @Override
        public void run() {
            c.x = 2;

        }
    });
    thread.start();
    try {
        thread.join();
        System.out.println(c.x);
    } catch (InterruptedException ex) {
        //
    }


}

如果不是,如果我想操纵一个我不控制其源代码的对象,比如一个集合,该怎么办?如何确保集合对象的更改对所有线程都可见?

对于第一个问题,是的。Volatile确保其他线程的读取操作可以看到对
Volatile
字段的写入。然而,它不是级联的,所以volatile并不适合所有用例(即,仅仅因为引用是volatile的,并不意味着引用对象的所有字段都会神奇地变为volatile)


在大多数情况下,您需要同步访问,以确保后续读取可以看到所有写入操作。

对于第一个问题,是的。Volatile确保其他线程的读取操作可以看到对
Volatile
字段的写入。然而,它不是级联的,所以volatile并不适合所有用例(即,仅仅因为引用是volatile的,并不意味着引用对象的所有字段都会神奇地变为volatile)


在大多数情况下,您需要同步访问,以确保后续读取可以看到所有写入操作。

对于第一个问题,是的。Volatile确保其他线程的读取操作可以看到对
Volatile
字段的写入。然而,它不是级联的,所以volatile并不适合所有用例(即,仅仅因为引用是volatile的,并不意味着引用对象的所有字段都会神奇地变为volatile)


在大多数情况下,您需要同步访问,以确保后续读取可以看到所有写入操作。

对于第一个问题,是的。Volatile确保其他线程的读取操作可以看到对
Volatile
字段的写入。然而,它不是级联的,所以volatile并不适合所有用例(即,仅仅因为引用是volatile的,并不意味着引用对象的所有字段都会神奇地变为volatile)


在大多数情况下,您需要同步访问,以确保后续读取可以看到所有写入操作。

对于您的示例,Varialbe x也必须是易失性的

如果是这样,如果我想操纵一个源代码为 不控制,例如收集?我如何确保 集合对象对所有线程都可见吗

要查看集合中的更改(假设它不是一个并发集合,假设它是一个普通的ArrayList),您应该自己提供一个监视器

Object monitor = new Object();

synchronized(monitor) {
   // change collection
}

synchronized(monitor) {
   // read collection
}
若读写操作将在监视器上同步,它们将正常工作。但是,如果您有不受控制的代码,并且该代码在不进行同步的情况下修改集合,则您将无能为力


问题2:即使在监视器上进行读/写同步,如果您在一个线程中迭代集合并在另一个线程中修改它,您仍然可以获得一些
ConcurrentModificationException
。因此,在我的示例中,read不是一个参考读取,而是一个值读取。

对于您的示例,Varialbe x也必须是易变的

如果是这样,如果我想操纵一个源代码为 不控制,例如收集?我如何确保 集合对象对所有线程都可见吗

要查看集合中的更改(假设它不是一个并发集合,假设它是一个普通的ArrayList),您应该自己提供一个监视器

Object monitor = new Object();

synchronized(monitor) {
   // change collection
}

synchronized(monitor) {
   // read collection
}
若读写操作将在监视器上同步,它们将正常工作。但是,如果您有不受控制的代码,并且该代码在不进行同步的情况下修改集合,则您将无能为力


问题2:即使在监视器上进行读/写同步,如果您在一个线程中迭代集合并在另一个线程中修改它,您仍然可以获得一些
ConcurrentModificationException
。因此,在我的示例中,read不是一个参考读取,而是一个值读取。

对于您的示例,Varialbe x也必须是易变的

如果是这样,如果我想操纵一个源代码为 不控制,例如收集?我如何确保 集合对象对所有线程都可见吗

要查看集合中的更改(假设它不是一个并发集合,假设它是一个普通的ArrayList),您应该自己提供一个监视器

Object monitor = new Object();

synchronized(monitor) {
   // change collection
}

synchronized(monitor) {
   // read collection
}
若读写操作将在监视器上同步,它们将正常工作。但是,如果您有不受控制的代码,并且该代码在不进行同步的情况下修改集合,则您将无能为力


问题2:即使在监视器上进行读/写同步,如果您在一个线程中迭代集合并在另一个线程中修改它,您仍然可以获得一些
ConcurrentModificationException
。因此,在我的示例中,read不是一个参考读取,而是一个值读取。

对于您的示例,Varialbe x也必须是易变的

如果是这样,如果我想操纵一个源代码为 不控制,例如收集?我如何确保 集合对象对所有线程都可见吗

要查看集合中的更改(假设它不是一个并发集合,假设它是一个普通的ArrayList),您应该自己提供一个监视器

Object monitor = new Object();

synchronized(monitor) {
   // change collection
}

synchronized(monitor) {
   // read collection
}
若读写操作将在监视器上同步,它们将正常工作。但是,如果您有不受控制的代码,并且该代码在不进行同步的情况下修改集合,则您将无能为力

问题2:即使在监视器上进行读/写同步,您仍然可以获得一些