Is ThreadPoolExecutor.execute() thread safe?

P

Philipp

Hello
I use a ThreadPoolExecutor and submit tasks using execute(Runnable).
It is not clear to me from the documentation if this method is thread
safe. Meaning, can I call it from different threads concurrently
without problems?

Further, I'm not using Sun's implementation of this class, but rather
the JVM 1.3 backport found at http://backport-jsr166.sourceforge.net
If anybody has a specific answer for this implementation, that would
be even better.

Thanks Phil
 
L

Lew

Philipp <wrote:
Just curious, why are you using an obsolete Java version?

One of the most significant changes starting with Java 5 (itself in
End-of-Life) was the repair of the broken (multi-threaded) memory model of
earlier versions.
 
L

Lew

Peter said:
If you are using a non-standard implementation, I suppose there's a chance  
it might not be thread-safe.  But I'd consider that a bug.

A similar question was just addressed recently:
<http://groups.google.com/group/comp.lang.java.programmer/
browse_thread/thread/b488770c7813276/e3282505343a6316?lnk=st&q=group
%3Acomp.lang.java.programmer+executor#e3282505343a6316>

Of course Executors are thread-safe. Duhy. That *is* their design
purpose after all, just like all of the java.util.concurrent packages.

The Javadocs point to this:
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.

That does not automatically mean that one's code written with them
will be thread-safe, of course. I suggest Brian Goetz (et al.)'s
excellent and seminal /Java Concurrency in Practice/ for training on
these matters.
Further, I'm not using Sun's implementation of this class, but rather
the JVM 1.3 backport found at http://backport-jsr166.sourceforge.net

The memory model in Java 1.3 (and 1.4) didn't have the /happens-
before/ semantics of Java 5 and later. It is possible that would mess
you up. Upgrade to the current Java version (6).
 
P

Patricia Shanahan

Peter said:
While the assumption seems reasonable on the face of it, the fact is I
could find no requirement in the Executor interface that implementors be
thread-safe. The docs for the java.util.concurrent package say
....

There is a general problem with vague documentation of thread safety.

This is a bit strange, because Sun decided to fix that for its Solaris
documentation several years ago. Each library function man page is
required to specify its "MT-Level". See, for example,
http://docs.sun.com/app/docs/doc/816-5168/memcpy-3c?a=view.

The permitted values and their meanings are specified, see
http://docs.sun.com/app/docs/doc/816-5175/attributes-5?a=view.

Here is an idea I am thinking of proposing:

1. Add to Javadoc a facility for specifying thread safety. There should
be a limited set of values, but not necessarily the same as the ones for
Sun's Solaris documentation.

2. Add an option to Javadoc to treat absence of a thread safety
specification for any public method or constructor as an error.

3. Encourage API developers, especially Sun's Java developers, to use
the option.

What do people think? Are the Sun Solaris MT-Level values a good
starting point?

Patricia
 
K

Knute Johnson

Peter said:
While the assumption seems reasonable on the face of it, the fact is I
could find no requirement in the Executor interface that implementors be
thread-safe. The docs for the java.util.concurrent package say

Depending on which concrete Executor class is being used,
tasks may execute in a newly created thread, an existing
task-execution thread, or the thread calling execute(),
and may execute sequentially or concurrently.

The docs for Executor.execute() say (in part);

The command may execute in a new thread, in a pooled thread,
or in the calling thread, at the discretion of the Executor
implementation.

Note that concurrent execution is _not_ mandatory from an Executor, and
so thread-safety may not be required for some specific Executor
implementation.

Now, the most recent question is about a specific implementation,
ThreadPoolExecutor. But even there, the documentation does not
specifically call the class or methods like execute() out as being
thread-safe.

Personally, I think it's a reasonable assumption that it would be.
After all, the usefulness of the class winds up _much_ reduced if it's
not thread-safe. But other thread-safe classes and/or methods in Java
are specifically described in the documentation as being so. It's a
fair question to wonder whether ThreadPoolExecutor is thread-safe, and
frankly even as confident I am that it is, I would hesitate to make a
_claim_ that it is without some specific documentation supporting the
claim.

So far, I haven't found that documentation. Do you know where it is?

Pete

The question is what does he mean by 'thread safe'? If he means the
call to execute(), then I'm sure that is safe (although I can't find
anything that says so). If he means the actions occurring in the task
then no, they must be protected as any other multi-threaded code.

If he means the call to execute() then putting it in a synchronized
block would be sufficient. But what would that actually protect? I
think it would only protect the actions of the execute() method which
just put the task into a BlockingQueue somewhere. There would be no
reason to synchronize that as the queue is already synchronized.

So barring some peculiarities of 1.3 and the back port, I think calling
execute() is thread safe.
 
P

Philipp

I take the question literally: is the method _execute()_ code safe?

Thank you Pete for putting it more clearly. Yes in fact, I am
interested to know if _execute()_ is thread safe, that is, if I can
submit new jobs to the Executor from different threads without
worrying about synchonization.
ThreadPoolExecutor specifically states it uses a BlockingQueue, so yes...I
agree that all queue operations will be thread-safe. But the execute()
method does other things than manipulating the queue.

Precisely. From what I read in this thread, there is no guarantee from
the docs that it is thread safe, but it can be assumed. I will just
have to rely on the fact that my implementation complies to that (or
check it myself). I guess that would be a good exercise :)

I also encourage a more strict inclusion of thread-safe info into docs
as proposed by Sabine.

Thanks to all for answers
Phil
 
L

Lew

Philipp said:
Precisely. From what I read in this thread, there is no guarantee from
the docs that it is thread safe, but it can be assumed. I will just
have to rely on the fact that my implementation complies to that (or
check it myself). I guess that would be a good exercise :)

If 'execute()' weren't thread-safe, the class wouldn't work. It is
thread-safe, in Java 5 and above.
 
J

John B. Matthews

Philipp said:
Thank you Pete for putting it more clearly. Yes in fact, I am
interested to know if _execute()_ is thread safe, that is, if I can
submit new jobs to the Executor from different threads without
worrying about synchonization.


Precisely. From what I read in this thread, there is no guarantee from
the docs that it is thread safe, but it can be assumed. I will just
have to rely on the fact that my implementation complies to that (or
check it myself). I guess that would be a good exercise :)

When I'm puzzling over such things, I've found it helpful to review
the API section entitled "Memory Consistency Properties":

<http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html>

In particular, "The results of a write by one thread are guaranteed
to be visible to a read by another thread only if the write operation
_happens-before_ the read operation." As Lew pointed out, "Actions in a
thread prior to the submission of a Runnable to an Executor
_happen-before_ its execution begins." As Pete suggested, this is not
proof that your code is correct. You still have to verify that your
program is correctly synchronized, as defined in the JLS, chapter 17,
section 4.5:

<http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.5>
 
T

Tom Anderson

...

There is a general problem with vague documentation of thread safety.

This is a bit strange, because Sun decided to fix that for its Solaris
documentation several years ago. Each library function man page is
required to specify its "MT-Level". See, for example,
http://docs.sun.com/app/docs/doc/816-5168/memcpy-3c?a=view.

The permitted values and their meanings are specified, see
http://docs.sun.com/app/docs/doc/816-5175/attributes-5?a=view.

I've also seen MT-hot, which i believe means that a function that is
MT-safe and can have multiple invocations executing concurrently - that's
stronger than MT-safe, which could involve a lock which only lets one
thread run it at once.
Here is an idea I am thinking of proposing:

1. Add to Javadoc a facility for specifying thread safety. There should
be a limited set of values, but not necessarily the same as the ones for
Sun's Solaris documentation.

How about an annotation rather than a javadoc thing?
2. Add an option to Javadoc to treat absence of a thread safety
specification for any public method or constructor as an error.

With an annotation, you could then get the compiler to complain instead of
javadoc.

The trouble with this mechanism is that it adds a burden when you're not
writing threaded code. I guess the idea is that you'd only use it when you
were.

How about being able to annotate a method as being threaded, then
requiring that all methods called by threaded methods be marked as
threadsafe? I can see lots of ways that wouldn't work, sadly.
3. Encourage API developers, especially Sun's Java developers, to use
the option.

What do people think?

I think it's a very good idea, and long overdue.
Are the Sun Solaris MT-Level values a good starting point?

To a point. We don't need Async-Signal-Safe, Fork-Safe or Cancel-Safety,
so really, we're looking at Safe, Unsafe and MT-Safe. I'm hazy on the
difference between Safe and MT-Safe - it seems to just be some wishy-washy
promises about concurrency. So basically, it comes down to Safe and Unsafe
- which is absolutely fine, but not something you can really say is
specifically taken from the Solaris levels!

I then worry about whether this terminology is rich enough for an OO
language. If there's a method which isn't safe to call in parallel on a
single object, but is fine to call in parallel on different objects (so
a.foo() and b.foo() is fine, but a.foo() and a.foo() is not), is that safe
or not? Presumably not. But then what do i call a method where it's not
safe to call it on separate objects at the same time? What if i have a
method which doesn't do anything unsafe to the object it's called on, but
does do so to its parameters? What if there are relationships between
objects, so a.foo() is only safe to call from the thread that is currently
executing b.bar()?

What would be great is if there was some solid computer-science foundation
for making statements about thread safety, so that each level had a really
well-defined meaning. I don't know enough to know if that's possible.

tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top