在Executors.newSingleThreadExecutor的后续调用之间进行线程安全

时间:2014-02-23 20:29:44

标签: java thread-safety executorservice

我有一个关于使用单线程执行程序的问题。由于它重用了相同的线程,这是否意味着如果我在一次提交调用中修改一个对象状态,我可以假设在后续的submit调用中对该对象状态的另一个修改是线程安全的吗?让我举个玩具示例......

public class Main {

    public static void main(String[] args) throws Exception {

        final A a = new Main().new A();
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Callable<Integer> callable = new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                return a.modifyState();
            }
        };

        /* first call */
        Future<Integer> result = executor.submit(callable);
        result.get();

        /* second call */
        result = executor.submit(callable);
        int fin = result.get();
        System.out.println(fin);

        executor.shutdown();
    }

    class A {

        private int state;

        public int modifyState() {
            return ++state;
        }

        public int getState() {
            return state;
        }

    }
}

所以我正在共享对象A.我提交一个可调用的并首先修改它的状态(参见/ *首先调用 /)。然后我做另一个提交电话,再次修改一个状态。 (/ 第二次电话* /)。现在我的大问题

是否安全地说,因为它是同一个线程,第二个提交调用会将A.state视为1?或者也可以在某些情况下将其视为0?

所以基本上我要问的是,在单个线程执行器的后续提交调用中修改未标记为从同步块中的volatile / access的变量是否安全?,因为它重用了相同的线程

线程重用对于执行者来说究竟是什么意思?在单线程执行程序的情况下,它是否与操作系统级别的线程完全相同?

2 个答案:

答案 0 :(得分:4)

它实际上并不重要,它是单线程的。 ExecutorService状态的javadoc:

  

内存一致性效果:在向ExecutorService提交Runnable或Callable任务之前的一个线程中的操作发生在该任务执行的任何操作之前,而该操作又发生在通过Future.get()检索结果之前

答案 1 :(得分:1)

Executors.newSingleThreadExecutor()通过保证一次只运行一个线程来为您提供线程安全性。它还为您提供了可见性,这意味着一个线程执行期间的任何状态更改都将对下一个线程执行可见。