ExecutorService是否保证线程安全?
我将把来自不同线程的作业提交到同一个ThreadPoolExecutor,在交互/提交任务之前,是否必须同步对执行者的访问?
(与其他答案相反)记录了线程安全协定:在interface javadocs中查找(与方法的javadoc相对)。例如,在ExecutorService javadoc的底部,您可以找到:
Memory consistency effects: Actions in a thread prior to the
submission of a Runnable or Callable task to an ExecutorService
happen-before any actions taken by that task, which in turn
happen-before the result is retrieved via Future.get().
这足以回答以下问题:
"do I have to synchronize access to the executor before interacting/submitting tasks?"
不,你不会。无需外部同步就可以构造作业并将其提交给任何(正确实施的)ExecutorService。这是主要的设计目标之一。
ExecutorService是并发实用程序,也就是说,它旨在在不进行同步的情况下最大程度地运行以提高性能。 (同步会导致线程争用,这可能会降低多线程效率,尤其是在扩展到大量线程时。)
无法保证在将来的什么时候任务会执行或完成(有些任务甚至可能在提交它们的同一线程上立即执行),但是可以保证工作线程已经看到了提交线程已经执行的所有效果。提交点。因此,您的任务(运行的线程)还可以安全地读取为使用而创建的任何数据,而无需同步,线程安全类或任何其他形式的"安全发布"。提交任务的行为本身足以将输入数据"安全发布"到任务。您只需要确保在任务运行时不会以任何方式修改输入数据。
同样,当您通过Future.get()取回任务的结果时,将确保检索线程可以看到执行者的工作线程所产生的所有效果(在返回的结果中,加上工作线程可能产生的任何副作用更改)取得了)。
该合同还意味着任务本身可以提交更多任务。
"Does the ExecutorService guarantee thread safety ?"
现在,这部分问题要笼统得多。例如,找不到关于方法shutdownAndAwaitTermination的线程安全协定的任何声明-尽管我注意到Javadoc中的代码示例未使用同步。 (尽管也许有一个隐藏的假设,认为关闭是由创建执行器的线程发起的,而不是由工人线程发起的?)