当前位置: 首页 > 知识库问答 >
问题:

仅由一个线程写入的易失性布尔开关是安全的吗?

柳正志
2023-03-14

我有以下代码:

public class Simulation
{       
    public static volatile boolean  IS_EVEN_TICK;
}

在另一个(可运行的)类中:

public void run()
{
    while (true)
    {
        // flip the "even/uneven tick" switch
        Simulation.IS_EVEN_TICK = !Simulation.IS_EVEN_TICK;
    }
}

据我所知,这通常不是线程安全的,因为写入到模拟。IS_EVEN_TICK取决于该变量的当前值。然而,这个线程是唯一写入变量的线程,所有其他线程只会读取变量(如果他们访问它)。

变量的易变性是否足以确保所有线程都从中读取正确的值,还是需要同步对变量的访问?

共有2个答案

澹台冯浩
2023-03-14

试着阅读规范并理解JMM,如果你的变量易失性这意味着变量将直接在堆中创建,并且没有一个处理器不将该值复制到自己的缓存中。

Volatile字段是用于在线程之间通信状态的特殊字段。对volatile的每次读取都会看到任何线程对该volatile的最后一次写入;实际上,程序员将它们指定为字段,因为缓存或重新排序的结果永远不会允许看到“过时”值

宓弘壮
2023-03-14

然而,这个线程是唯一写入变量的线程...变量是否足够不稳定,以确保所有线程都从中读取正确的值。

如果只有一个作者,那么就没有种族条件。不需要跨变量同步。

您可以考虑使用<代码> AtomicBoolean <代码>,但它不支持<代码> ToGeLe[()/<代码>方法,因此,如果您有多个写入器切换该值,则必须执行如下操作:

private final AtomicBoolean isEvenTick = new AtomicBoolean();
...
boolean currentValue;
do {
  currentValue = isEvenTick.get();
} while (!isEvenTick.compareAndSet(currentValue, !currentValue);
 类似资料:
  • 最近我在读一些关于java并发的书。关于线程安全,如果不可能使一个类变为inmutable,那么可以通过同步它的数据来确保线程安全。 下面的类显然不是线程安全的 然后我可以同步写,但它不会保持线程安全 因为我不仅需要同步写入,还需要同步读取 现在的问题是,通过使用易失性,我可以保证其他线程会看到更新的值,所以这让我认为这个类应该是线程安全的 最后一个类线程安全吗??

  • 问题内容: servlet是线程安全的吗?例如,如果我打开5个不同的浏览器并向容器中的一个servlet发送请求,它是否仍然是线程安全的,我特别指的是方法 问题答案: 您的问题可以归结为: 正在从同一对象线程safe上的多个线程调用方法 。答案是: 取决于 。如果您的对象(让它成为servlet)是无状态的或仅具有字段,则这是完全线程安全的。局部变量和参数是线程局部的(驻留在堆栈上,而不是堆上)。

  • 我正在阅读JCIP,无法理解3.3.1中的以下语句, 对共享的易失性变量执行读-修改-写操作是安全的,只要可以确保仅从单个线程写入易失性变量。在本例中,您将修改限制在单个线程中,以防止出现争用情况,并且volatile变量的可见性保证确保其他线程看到最新的值。 即使挥发性变量只从单个线程写入,它怎么能不提高竞争条件?如果线程A在计数器为1时执行,线程B可以在计数器1写入内存之前进入,并获得的旧值1

  • 根据JLS 17规范第17.3节: 例如,在下面的(断开的)代码片段中,假设这是。“完成”是一个非易失性布尔字段: 编译器可以自由读取此字段。只执行一次,并在每次执行循环时重用缓存的值。这意味着循环永远不会终止,即使另一个线程更改了这个值。完成 我尝试模拟以下示例:两个线程同时访问同一个布尔变量,第一个线程使用while循环中的共享布尔值,第二个线程更新布尔值。 1、代码无线程。第一个线程内的sl

  • tcp套接字是具有双向读写功能的endpoint。在java中,我们可以获得套接字的InputStream和OutputStream。 同时使用这些流是否安全? 据我所知,有一个连接能够在任何给定时间从一个endpoint发送或接收到其他数据。 我正在基于SocketChannels实现nio传输层,我想保留一个线程用于所有写入,一个线程用于接受和读取,但我不确定如果我的线程同时尝试在同一个套接字

  • 问题内容: 阅读“实践中的Java并发性”,第3.5节包含以下内容: 除了创建两个的明显的线程安全隐患外,该书还声称可能会发生发布问题。 此外,对于诸如 一个可以扔! 这怎么可能?我能想到的唯一允许这种荒谬行为的方法是,如果构造函数不被阻塞,那么当构造函数代码仍在另一个线程中运行时,将创建对实例的引用。 这可能吗? 问题答案: 之所以可行,是因为Java的内存模型较弱。它不保证读写顺序。 可以通过