有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java非易失性变量是否需要同步?

考虑2个线程和一个数组^ {CD1>}。 第一个线程正在执行:

synchronized (values) {
     values[i] = 58;
}

当第二个线程正在执行时:

if (values[i] == 58) {
}

synchronized块之外

如果第一个线程首先执行values[i]= 58,是否可以保证如果第二个线程执行得稍晚,即使第二个线程在synchronized块外读取58,第二个线程的if也会读取58


共 (2) 个答案

  1. # 1 楼答案

    上述行为不能保证。这种“可见性”的保证实际上是关系发生之前的主题:

    The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.

    在实现关系(according to JLS)之前发生:

    1. 线程中的每个动作都发生在该线程中的每个动作之前,该线程中的每个动作都是按照程序的顺序稍后出现的
    2. 监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法进入)之前。而且因为“发生在之前”关系是可传递的,所以在解锁之前线程的所有操作都发生在监视的任何线程锁定之后的所有操作之前
    3. 对易失性字段的写入发生在对该字段的每次后续读取之前。易失性字段的写入和读取与进入和退出监视器具有类似的内存一致性效果,但不需要互斥锁定
    4. 对线程的启动调用发生在已启动线程中的任何操作之前
    5. 线程中的所有操作都发生在任何其他线程从该线程上的联接成功返回之前

    因此,在您的特定情况下,您实际上需要使用共享监视器或AtomicIntegerArray进行同步,以确保对阵列线程的访问安全volatile修饰符不会起作用,因为它只影响指向数组的变量,而不会影响数组的元素(more detailed explanation

  2. # 2 楼答案

    If the first thread first performs values[i]= 58, is it guaranteed that if the second threads executes slightly later, that the if of the second thread reads 58 even though the second thread reads values[i] outside a synchronized block?

    没有

    以这种方式同步不会停止其他线程同时对阵列执行任何操作。但是,将阻止其他线程获取阵列上的锁