gpt4 book ai didi

java - 如何理解 "The variable does not participate in invariants with other state variables when using volatile keyword"?

转载 作者:搜寻专家 更新时间:2023-10-30 21:46:12 24 4
gpt4 key购买 nike

摘自《Java 并发实践》第 26 页:

仅当满足以下所有条件时,您才能使用 volatile 变量:

  • 对变量的写入不取决于其当前值,或者您可以确保只有一个线程永远更新该值;

  • 该变量不参与与其他状态变量的不变量;和

  • 在访问变量时,不需要出于任何其他原因进行锁定。

如何理解“使用 volatile 关键字时变量不与其他状态变量参与不变量”?

最佳答案

“不变”的简单定义:在对象的生命周期内始终为真的条件

Volatile variables do not share the atomicity features of synchronized blocks.

这就是为什么您不能在具有与多个变量相关的不变量的类中使用它们。

例如,假设您有一个 class 来模拟由两个变量描述的时间间隔:startend。一个不变的条件可能是 start 总是小于或等于 end。如果两个变量(仅作为示例)都声明为 volatile,那么您可以依赖 volatile 的可见性功能,但您不能确定在涉及两个变量的更改期间始终满足不变量。思考:

public void setInterval(Date newStart, Date newEnd)
{
// Check if inputs are correct

// Here the object state is valid
start = newStart;

// If another thread accesses this object now it will
// see an invalid state because start could be greater than end

end = newEnd;
// Here the object state is valid again
}

在这种情况下,您可以确定更改对每个线程都是可见的,但在两条指令的中间,对象状态可能无效。因为它可以被其他线程访问(请记住这是一个简单的情况,所以它是可能的但不太可能)那么不变条件“start < end”可能会被打破。

这就是为什么在(小)一组明确定义的模式之外以某种方式不鼓励使用 volatile 的原因。仅当满足这些条件时才应使用 volatile 变量:

  • 该变量不涉及与其他变量相关的不变量(原因如上所述)。
  • 写入变量的值不依赖于它的当前值。

例如表达式 int a = i++; 不是原子的,那么它不是 - 严格来说 - 线程安全的,因为它会被 重写 像这样:

int temp = i;
i = i + 1;
int a = temp;

从线程的角度来看,要使其成为原子,您可以想象这样一个类:

public class MyAtomicInteger
{
public synchronized increment()
{
x = x + 1;
}

private int x;
}

当然它存在这个AtomicInteger 的真正实现并且它是包java.util.concurrent.atomic 的一部分,它为无锁并发编程提供了一些简单的基本例程。

关于java - 如何理解 "The variable does not participate in invariants with other state variables when using volatile keyword"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9868577/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com