5

我有一个班级组织如下:

public class MyClass {

   ExecutorService pool;

   public MyClass(){
     pool = ... //inited by a class that implements ExecutorService
   }

   public final void submit(Runnable run){
        pool.execute(run);
   }
}

该方法是submit线程安全的还是我应该使用Lock基于 - 的系统?例如

   ReentrantLock look  = new ReentrantLock();

   public final void submit(Runnable run){
        lock.lock();
        try{ pool.execute(run); } finally{lock.unlock();}
   }
4

2 回答 2

8

不,调用ExecutorService#submit时不需要锁。

内存一致性效果:在将 Runnable 或 Callable 任务提交给 ExecutorService 之前,线程中的操作发生在该任务采取的任何操作之前,这反过来又发生在通过 Future.get() 检索结果之前。

或者在调用Executor#execute时:

内存一致性效果:在将 Runnable 对象提交给 Executor 之前,线程中的操作发生在其执行开始之前,可能在另一个线程中。

于 2013-04-17T11:11:43.373 回答
1

这取决于您ExecutorService的访问方式或您MyClass的创建方式。如果MyClass在单个线程中创建实例并且#poolivar 也在单个线程中创建,则此类是线程安全的,并且您的使用#pool是线程安全的。

但是,如果您MyClass可以跨多个线程存在(例如首先通过单例、共享工厂或共享列表访问 - 即不是new MyClass()),那么它不是线程安全的。这是因为多个线程可以访问您的Myclass实例及其单个#poolivar。调用提交可以完成,但一次有多个线程,因此您的Myclass实例的状态或pool可能会受到损害。在这种情况下,您MyClass#submit应该通过锁进行同步或管理。由于这是一种小方法,我建议只同步#submit.

同样,如果您的MyClass实例是在此线程中创建的,但未在此线程#pool中创建为新实例(pool = new AnExecutorPoolType(...);那么此类将再次不是线程安全的。可以再次从跨多个线程可用的另一个源(如上)访问池。如果如果是这种情况,那么它就有可能被多个线程访问置于不一致的状态。在这种情况下,该pool#execute方法应该同步(或通过同步块保护 ivar 访问)或通过锁进行管理。

于 2013-04-17T11:18:28.550 回答