Reputation: 13666
I have a class organized as follows:
public class MyClass {
ExecutorService pool;
public MyClass(){
pool = ... //inited by a class that implements ExecutorService
}
public final void submit(Runnable run){
pool.execute(run);
}
}
Is the method submit
thread safe or I should use a Lock
-based system? E.g.
ReentrantLock look = new ReentrantLock();
public final void submit(Runnable run){
lock.lock();
try{ pool.execute(run); } finally{lock.unlock();}
}
Upvotes: 5
Views: 5527
Reputation: 6288
This depends on how your ExecutorService
is accessed or how your MyClass
is created. If an instance of MyClass
is created in a single thread and the #pool
ivar is also created in a single thread then this class is thread-safe and your use of #pool
is threadsafe.
However, if your MyClass
can exist across multiple threads (such as first accessed through a singleton, shared factory or shared list - i.e. not new MyClass()
) then it is not thread-safe. This is because multiple threads could access your Myclass
instance and its single #pool
ivar. Calling submit could be done but multiple threads at once and so the state of your Myclass
instance or pool
could be compromised. In this case, your MyClass#submit
should be synchronised or managed by locks. As it's a petite method, I'd suggest just synchronising #submit
.
Likewise, if your MyClass
instance is created in this thread but #pool
is not created as new in this thread (pool = new AnExecutorPoolType(...);
then this class would again not be threadsafe. The pool may again be accessed from another source(as above) that is available across multiple threads. If that's the case then there is a risk of it being left in an inconsistent state by multiple thread accesses. In this case, the pool#execute
method should be synchronised (or through a synchronised block guarding ivar access) or managed through locks.
Upvotes: 2
Reputation: 328568
No you don't need the lock when calling ExecutorService#submit.
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().
or when calling Executor#execute:
Memory consistency effects: Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.
Upvotes: 8