当前位置: 首页 > 面试题库 >

是否保证在一个线程中对非易失性成员变量的分配可以在另一个线程中看到?

宰父德馨
2023-03-14
问题内容

考虑下面的Java示例。请注意,两个类成员变量都没有声明为volatile。如果我正确地理解了内存模型并理解了“之前发生”的规则,那么Java实现可以优化该run()方法,使其永远运行,即使另一个线程调用该stopNow()方法也是如此。之所以会发生这种情况,是因为该run()方法中没有任何东西可以强制线程读取多个值stop。那是对的吗?如果没有,为什么不呢?

class Example implements Runnable {
    boolean stop = false;
    int value = 0;

    public void stopNow() {
       stop = true;
    }

    public int getValue() {
        return value;
    }

    @Override
    public void run() {
        // Loop until stop is set to true.
        while (!stop) {
            ++value;
        }
        return;
    }
}

问题答案:

可以由另一个线程修改,但这不是保证。这也不是线程安全的。要使变量保证从另一个线程查看,您需要执行以下任一操作

仅在以下情况下,才能保证一个线程对字段所做的更改仅对其他线程可见:

  • 写入线程释放同步锁,而读取线程随后获取该相同的同步锁。
  • 如果将一个字段声明为易失性字段,则在写入
    线程执行任何进一步的内存操作之前,写入该线程的任何值都会被写入线程并使写入线程可见(即,出于
    手头的目的,将立即刷新该字段)。读取器线程必须
    在每次访问时重新加载volatile字段的值。


  • 线程第一次访问对象的字段时,它将看到该字段的初始值或自其他线程写入以来的值。
  • 线程终止时,所有写入的变量都将刷新到主内存。例如,如果一个线程使用Thread.join在另一个线程的终止上进行同步,则可以保证看到该
    线程产生的效果(请参见第4.3.2节)。


 类似资料:
  • 我正在考虑一个语句的示例“在一个线程中获取许可证,然后从另一个线程中释放”。 我对信号量的理解是,它维护一组许可。Thread应在通过临界截面之前获得许可证,然后许可证递减1。一旦Thread完成临界截面,它将释放许可证,许可证将增加1<示例: 1。ATM机,配备一名保安,根据机器的可用性允许人们使用。机器越多,许可证就越多。一位客户购买了一台ATM机,完成后将其释放 2。银行的柜台,如果柜台空闲

  • 我正在阅读这篇文章,关于从一个线程中断另一个线程的建议是 “”“如果正确实施,以下几种方法应该可以奏效。 您可以让两个线程定期检查一些常见的标志变量(例如,将其称为stopNow),并安排两个线程在完成时进行设置。(标志变量需要是volatile…或正确同步的。) 您可以让两个线程定期调用线程。isInterrupted()方法,查看它是否已被中断。然后每个线程都需要调用线程。完成后,在另一个上中

  • 问题内容: 我正在对此进行研究,以了解新JMM(从5开始)中最终字段的行为。这个概念很明确:在正确构造对象之后,可以保证初始化的最终字段对所有线程的可见性。 但是,在本节的最后,我读到了这,这简直让我感到困惑: 综上所述,如果在线程构造了一个不变对象(即仅包含最终字段的对象)之后,您想要确保所有其他线程都能正确看到该对象,则通常仍然需要使用同步。没有其他方法可以确保,例如,第二个线程将看到对不可变

  • 在一个android服务中,我创建了用于执行一些后台任务的线程。 我遇到一个情况,线程需要在主线程的消息队列上发布特定任务,例如。 有没有方法获取主线程的并从我的另一个线程向它发布/?

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

  • 我有一个疑问相对于UI线程和其他线程之间的concurrency。 Ui主线程更新不同变量的值:-flol-long-boolean 我还有另一个线程,它读取同一个变量,并用它执行一些逻辑操作(不编辑它的值),然后用这个操作的结果发送本地广播消息。 是否存在并发问题???我必须使用同步方法和原子变量,否则就无关紧要了? 我反思这个问题,因为没有浮点基元的原子变量,也因为我害怕用错误的代码阻止Ui线