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

即使只有一个writer线程,volatile也会有问题吗

杜成和
2023-03-14

如果有一个写入线程和一个读取线程,我们仍然可以有一个具有易失性变量的竞争条件。就像下面的代码一样,在一种情况下,编写线程检查x值为零,没有发生上下文切换,读取线程也看到x值为0。在一种情况下,写入线程检查x的值为零,递增1,将其刷新到主存储器(因为x是易失性的),发生上下文切换,读取线程将x的值视为1。我只是想知道在这个用例中,挥发性是否足够,或者我们需要使用同步来避免竞争条件

我试过执行下面的代码,但结果总是一样的

public class VolatileSingleWriterClarity {
    static volatile int x = 0;

    public static void main(String[] args) {
        new Thread(VolatileSingleWriterClarity::writer).start();
        new Thread(VolatileSingleWriterClarity::reader).start();
    }

    public static void reader() {
        System.out.println(x);
    }

    public static void writer() {
        x++;
    }
}

共有1个答案

华项明
2023-03-14

就像下面的代码一样,在一种情况下,编写线程检查x值为零,没有发生上下文切换,读取线程也看到x值为0。

是的,这是绝对可能的。尽管x是易失性的,x涉及两个完全独立的操作:易失性读取,然后是易失性写入。这些操作中的每一个都是原子操作,但它们之间绝对有可能发生上下文切换。(这两个线程也可以在完全独立的处理器内核上运行,因此即使没有上下文切换,读卡器也可以在编写器即将编写新值时读取原始值。)

我只是想知道在这个用例中,挥发性是否足够,或者我们需要使用同步来避免竞争条件

同步在这里不会真正有帮助。您似乎担心防止这种情况(易失性允许但同步可以防止):

  • 写入线程读取x

但它完全等同于这种情况(这两种情况都是volatilesynchronized允许的):

  • 读卡器线程读取x的原始值,并打印它

因此,没有必要“修复”一个而不修复另一个。

如果要确保读卡器线程在写入线程之前不读取x,则需要执行更复杂的操作,例如使用waitnotify

 类似资料:
  • 我目前分析了我的kafka制作人Spring boot应用程序,发现许多“kafka制作人-网络-线程”正在运行(总共47个)。即使没有发送数据,它也永远不会停止运行。我的应用程序看起来有点像这样: 与KafkaSender: 因为每次我想给kafka发送消息时,我都会引用一个新的KafkaSender,所以我认为会创建一个新的线程,然后将消息发送到Kafka队列。目前看起来像是产生了一批生产者,

  • 在Flink中,像“平面地图”、“地图”等运算符称为任务,如果我将平面地图的并行度设置为30,那么这个任务有30个子任务。 现在,如果我只有一个插槽,它会在一个插槽中产生多个线程吗?还是每个插槽只有一个线程? Flink会在该插槽中简单地创建30个线程,还是使用类似线程池的东西? 以上不是一个恰当的例子。 假设在作业中我有操作符flatMap和map,它们都有并行度1,我只有一个插槽,这个插槽会创

  • 问题内容: 我有这种简单的查询,它返回给定id的非空整数字段: 问题是,如果找不到ID,则结果集为空。我需要查询始终返回一个值,即使没有结果也是如此。 我有这个东西工作,但我不喜欢它,因为它运行相同子查询的2倍: 如果该行存在,则返回field1,否则返回0。有什么改进的方法吗? 谢谢! 编辑以下一些评论和答案 :是的,它必须在 单个查询语句中, 并且我不能使用count技巧,因为 我只需要返回1

  • 我用的是Netty camel-Netty:jar:2 . 10 . 0 . red hat-60024。下面是我对Netty监听器的配置 荨麻:tcp://10.1.33.204:9001?textline=true 在这里,我看到基于调试日志,Netty只创建一个工作线程,所以传入的消息被阻塞,直到现有的消息被处理。 喜欢: 2014-08-23 12:36:48,394|DEBUG|w I/

  • 本文向大家介绍解决ROC曲线画出来只有一个点的问题,包括了解决ROC曲线画出来只有一个点的问题的使用技巧和注意事项,需要的朋友参考一下 之前在做kaggle比赛时,有个比赛使用AUC来评比的,当时试着画了ROC曲线,结果出来的下图这样的图形。跟平时的ROC曲线差好远,就只有一个点。而别人家的都是很多转折的,为啥我的不一样。 我的图如下: 正常的图(sklearn上面截取的): 思考过后,发现原来:

  • 问题内容: 我正在阅读揭露java.lang.Out OfMemoryError,我想知道我是否正确理解它。的确,如果Java VM抛出 :请求的阵列大小超出VM限制 这意味着VM拒绝了数组的创建,因为它已经超出了预定义的限制(超出了VM的限制),而 不是 因为我的堆空间用完了吗? 我是否可以说这并不表示记忆不足? 即使我有 无限的 记忆 无处不在 ,Java虚拟机仍然可以抛出,如果它不喜欢我的请