简体   繁体   English

混淆 java 线程变量可见性

[英]confuse about java thread variable visibility

All example I found which talk about visibility is example with primitive type.我发现的所有关于可见性的例子都是原始类型的例子。 What I want to know is: if a object which new in heap, when one thread call its method to change its state, without locking or synchronize, other thread will see this change?我想知道的是:如果一个 object 在堆中是新的,当一个线程调用它的方法来改变它的 state 时,没有锁定或同步,其他线程会看到这个变化吗? Imagine a Java.Colletion object, one thread call its add() method想象一个Java.Collection object,一个线程调用它的add()方法

Someone says for object in heap still has visibility problem, but the JLS said: 17.4.1 Shared Variables Memory that can be shared between threads is called shared memory or heap memory. Someone says for object in heap still has visibility problem, but the JLS said: 17.4.1 Shared Variables Memory that can be shared between threads is called shared memory or heap memory.

and http://www.artima.com/insidejvm/ed2/jvm2.html said: A thread's Java stack stores the state of Java (not native) method invocations for the thread. and http://www.artima.com/insidejvm/ed2/jvm2.html said: A thread's Java stack stores the state of Java (not native) method invocations for the thread. The state of a Java method invocation includes its local variables, the parameters with which it was invoked, its return value (if any), and intermediate calculations. Java 方法调用的 state 包括其局部变量、调用它的参数、其返回值(如果有)和中间计算。

So I think, JVM will not copy a object which in heap to CPU cache.所以我认为, JVM 不会将堆中的 object 复制到 CPU 缓存中。 If this is correct, object in heap won't have visibility problem, because thread just reference to the object in heap.如果这是正确的,堆中的 object 不会有可见性问题,因为线程只是引用堆中的 object。

BTW Assume there is concurrent problem when one thread call.add().顺便说一句,假设一个线程调用.add() 时存在并发问题。 In normal process, the change must guard with a lock, so this problem is not a problem.在正常的过程中,更改必须带有锁,所以这个问题不是问题。 But I just want to know:)但我只想知道:)

The answer is "no, the other thread will not necessarily see the change to the Collection", because (most of) the standard Collections are not thread-safe - that is, they do not have safe publication of their state.答案是“不,其他线程不一定会看到对集合的更改”,因为(大部分)标准 Collections 不是线程安全的 - 也就是说,他们没有安全发布其 state。 (The other thread may, or may not see the change). (另一个线程可能会,也可能不会看到变化)。

That is why the java.util.concurrent package was created - it provides thread-safe implementations of java.util.Collections. That is why the java.util.concurrent package was created - it provides thread-safe implementations of java.util.Collections.

You can still perform memory synchronisation without synchronized if you have volatile , atomic variables, or other concurrent containers that provide happens-before semantics.如果您有volatile 、 atomic 变量或其他提供happens-before语义的并发容器,您仍然可以在没有synchronized的情况下执行 memory 同步。 However, if you do none of those things, then nothing is guaranteed with regard to memory visibility.但是,如果您不执行任何这些操作,那么 memory 可见性就无法保证。

In your particular case, if you want to call add() on a container in one thread and have it be visible in another without explicit locking, then this will only work if the container is a concurrent one (eg, one of the ones in the java.util.concurrent package), or a synchronised one (eg, Collections.synchronizedList ).在您的特定情况下,如果您想在一个线程中的容器上调用add()并使其在另一个线程中可见而无需显式锁定,那么这仅在容器是并发容器时才有效(例如,在java.util.concurrent包)或同步包(例如Collections.synchronizedList )。

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

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