由线程池运行runnable,我应该使用volatile吗?

时间:2016-12-27 14:21:47

标签: java multithreading volatile

像下面的示例代码一样。

我将使用线程池在期间运行TestRunnable的对象。

我应该将变量total声明为volatile吗?

public class TestRunnable implements Runnable {
    private int total;
    @Override
    public void run() {
        if (total > 10) {
            return;
        } else {
            total += 1;
            System.out.print("Run in times: " + total);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

假设您的变量被声明为

 private int total;

(非静态)

它不会在多个线程之间共享(只要您继续为每个提交的线程创建新实例),所以不需要将其声明为volatile。

如果您多次使用同一个实例 - 那么您应该考虑使用 AtomicInteger 而不是常规 int ,因为操作

total+= 1;

total++;

不是原子操作,可能会导致多线程环境中出现意外结果。

答案 1 :(得分:0)

即使您要标记字段volatile,由于if语句不是原子的,因此没有任何价值。请考虑以下情况:

  1. 一个线程执行TestRunnable' run()方法。
  2. 表达式total > 10的评估结果为false,因为total为10。
  3. 结果,线程进入else分支并尝试增加变量。
  4. 另一个主题也是如此,但total尚未增加。
  5. 现在,两个线程都递增total,这可能会使其处于不一致状态。
  6. 请注意,只有在您向池中多次提交相同的实例时才会发生这种情况(至少这是我能想到的唯一情况)。但是,由于您在Runnable内管理状态 - 这对我来说似乎不对,这可能是您正在做的事情。

    正如@DmitriyKotov指出的那样,您应该切换到AtomicInteger。从Java 8开始,您可以轻松完成:

    total.getAndUpdate(currentVal -> currentVal > 10 ? currentVal : currentVal + 1);