无论线程如何,对象是否始终看到其最新的内部状态?

假设我有一个可运行的,它有一个简单的整数计数变量,每次可运行运行时都会递增。提交此对象的一个实例以在计划的执行程序服务中定期运行。


class Counter implements Runnable {

    private int count = 0;


    @Override

    public void run() {

      count++;

    }

}


Counter counter = new Counter();

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);

executorService.scheduleWithFixedDelay(counter, 1, 1, TimeUnit.SECONDS);

在这里,对象正在访问不同线程内自己的内部状态(读取和递增)。此代码是线程安全的,还是当变量在其他线程中调度时,我们是否会丢失对变量的更新?count


慕标琳琳
浏览 70回答 3
3回答

万千封印

无论线程如何,对象是否始终看到其最新的内部状态?为了清楚这个问题及其答案的目的,一个物体不做任何事情;它只是记忆。线程是执行实体。说一个物体能看到什么东西是误导性的。它是执行对象状态的查看/读取的线程。这在爪哇语中没有指定,但是Executors.newScheduledThreadPool(5);返回 .ScheduledThreadPoolExecutor您的代码正在使用executorService.scheduleWithFixedDelay(counter, 1, 1, TimeUnit.SECONDS);调度线程池资源管理器#scheduleded与固定状态的 javadoc提交一个周期性操作,该操作在给定的初始延迟之后首先启用,随后在一个执行终止和下一个执行开始之间的给定延迟下启用。爪哇类进一步澄清通过或不重叠计划的定期任务的连续执行。虽然不同的执行可能由不同的线程执行,但先前执行的效果发生在后续执行之前。scheduleAtFixedRatescheduleWithFixedDelay因此,保证 每个执行 都可以看到 在上一次执行递增后的值。例如,第三次执行将读取一个值,然后再执行其增量。Counter#runcountcount2对于此特定用例,您不需要或任何其他附加的同步机制。volatile

胡说叔叔

不,此代码不是线程安全的,因为在以 开始的不同线程中所做的增量之间没有任何发生任何关系。ScheduledExecutorService要修复此问题,您需要将变量标记为 或切换到 或 。volatileAtomicIntegerAtomicLong更新:@BoristheSpider 如前所述,一般来说,在递增/递减的情况下,做一个变量是不够的,因为递增/递减本身不是原子的,并且同时从多个线程调用它将导致争用条件和错过更新。但是,在这种特殊情况下,保证(根据Javadoc)计划任务的重叠执行,因此即使在增量的情况下,也在此特定情况下也有效。volatilescheduleWithFixedDelay()volatile

噜噜哒

不,此代码不是线程安全的,因为在访问 的不同线程之间的关系之前不会发生任何事件。count
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java