How do I use the Java API in a Thread-Safe Manner?

A

Al Koch

Thanks Dale,

Dale King said:
Eric Sosman wrote:
There has been discussion in this group and on the web in reference to
"double-checked locking" that a VM can set a variable to reference the
newly created object before the objects constructor has actually
completed, which would allow another thread to access an object before
its construction is complete.

Things get really complicated when you start talking about mulitple
processors and the memory model.

See for example, the following:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Here's a related reference -
http://www.javaworld.com/jw-02-2001/jw-0209-double.html

Al,
(e-mail address removed)
 
A

Al Koch

Hi Dale,
You seem to have a lot to learn about what it really means to be "thread
safe". Yes most of the API is not thread safe in that it is not safe for
multiple threads to be calling methods on an instance without some sort
of synchronization mechanism. That is not a bad thing.

Thread safety does not begin and end with the Java API. Even if every
method in the Java API were synchronized that would not in and of itself
guarantee much of anything about the thread safety of any program that
used those API's. Thread safety involves how an API is used as well.

Consider if I had a class that maintained its state using a Vector and a
Hashtable. Both of those classes are thread safe in that you can make
calls on an instance from multiple threads and the internal state of the
Hashtable or Vector will be consistent. But in my class that uses them
if I add an item it needs to be added to the Hashtable and Vector. If I
don't do synchronization within my class then I can still end up with an
inconsistent state between the Hashtable and Vector.

Since most thread safety issues involve big picture issues like this it
is rather pointless (and quite harmful from a performance standpoint) to
have the low level API's try to be thread safe (and giving users a false
sense of security). Most of the time an API will only be accessed from
one thread any way. They therefore elect to put the burden on the user
to determine the best way to make it thread safe, but provide some
optional low level thread safety on the very simple classes like the
collection classes and StringBuilder vs. StringBuffer.

I understand that we cannot just take an API that is marked "thread safe"
and blindly use it; it is essential that we look at how it is used from a
higher level. I also understand that it can make sense to push the
responsibility for thread-safety to the calling client level for perfomance
raesons as well. However, if we are starting with an API that *may or may
not* itself be thread-safe" aren't we having to deal with a greater level of
uncertainty than is necessary than if the documentation made a clear
statement? For example, the IOImage class is not documented as being safe
or unsafe. However, we know that a static member such as
IOImage.createImageInputStream() is static so that means (as I understand
it) that it manipulates at least one Class variable. If my thread is in the
middle of executing createImageInputStream() and another thread enters this
function don't I need to be concerned?

I just realized that in the example I just gave that I mixed two of my
problems/areas of concern which are:
1) Can you speculate on why Sun wouldn't make a statement like "none of the
API is thread-safe unless we state otherwise" so we can know with certainity
that we are building a block of code that uses an API that is itself either
thread-safe or not
2) In any case, how can we synch on a J2SE/EE static method such as
createImageInputStream()? I can ensure that all of *my* code (and hence
threads) are synched, but since this API is available to any other
application running in the JVM there's no way I can ensure that some other
thread won't interrupt my thread in the middle of such a static method. Are
we reduced in this situation to having to obtain and study the API source
itself to see if we have a problem?

Thanks,
Al,
(e-mail address removed)
 
R

Raymond DeCampo

Al said:
Hi Dale,




I understand that we cannot just take an API that is marked "thread safe"
and blindly use it; it is essential that we look at how it is used from a
higher level. I also understand that it can make sense to push the
responsibility for thread-safety to the calling client level for perfomance
raesons as well. However, if we are starting with an API that *may or may
not* itself be thread-safe" aren't we having to deal with a greater level of
uncertainty than is necessary than if the documentation made a clear
statement? For example, the IOImage class is not documented as being safe
or unsafe. However, we know that a static member such as
IOImage.createImageInputStream() is static so that means (as I understand
it) that it manipulates at least one Class variable.

This is not a valid assumption. In fact, I would imagine that most
static methods only manipulate local variables.
If my thread is in the
middle of executing createImageInputStream() and another thread enters this
function don't I need to be concerned?

In general, I would assume that static methods are thread safe. Any
static method that is not would be considered to be broken by any
reasonable software engineer.
I just realized that in the example I just gave that I mixed two of my
problems/areas of concern which are:
1) Can you speculate on why Sun wouldn't make a statement like "none of the
API is thread-safe unless we state otherwise" so we can know with certainity
that we are building a block of code that uses an API that is itself either
thread-safe or not
2) In any case, how can we synch on a J2SE/EE static method such as
createImageInputStream()? I can ensure that all of *my* code (and hence
threads) are synched, but since this API is available to any other
application running in the JVM there's no way I can ensure that some other
thread won't interrupt my thread in the middle of such a static method. Are
we reduced in this situation to having to obtain and study the API source
itself to see if we have a problem?

Thanks,
Al,
(e-mail address removed)

HTH,
Ray
 
B

Bjorn Borud

["Al Koch" <[email protected]>]
|
| However, if we are starting with an API that *may or may not* itself
| be thread-safe" aren't we having to deal with a greater level of
| uncertainty than is necessary than if the documentation made a clear
| statement?

the documentation should always say something about the thread safety
issues a class might have. (although I'd be the first to admit that I
often forget to document this myself unless it is some API that is
meant to be exposed to other developers).

| For example, the IOImage class is not documented as being safe or
| unsafe. However, we know that a static member such as
| IOImage.createImageInputStream() is static so that means (as I
| understand it) that it manipulates at least one Class variable.

it being static doesn't necessarily imply it has to manipulate static
variables.

| If my thread is in the middle of executing createImageInputStream()
| and another thread enters this function don't I need to be
| concerned?

there are four ways for an API author to handle this:

- ensure the method doesn't alter any state or depend on any
state that could be changed by another thread.

- declare the method synchronized, thereby implying it does alter or
depend on state and saying what is used for synchronization

- do explicit synchronization inside the method

- not do any synchronization and document its thread safety
issues if they exist

all of them are valid ways of handling the same problem and what you
choose is mostly decided by how you intend the code to be used and
what your tastes are.
|
| I just realized that in the example I just gave that I mixed two of my
| problems/areas of concern which are:
| 1) Can you speculate on why Sun wouldn't make a statement like "none of the
| API is thread-safe unless we state otherwise" so we can know with certainity
| that we are building a block of code that uses an API that is itself either
| thread-safe or not
| 2) In any case, how can we synch on a J2SE/EE static method such as
| createImageInputStream()? I can ensure that all of *my* code (and hence
| threads) are synched, but since this API is available to any other
| application running in the JVM there's no way I can ensure that some other
| thread won't interrupt my thread in the middle of such a static method. Are
| we reduced in this situation to having to obtain and study the API source
| itself to see if we have a problem?

it takes a a while to develop a proper understanding of concurrent
programming and the issues that often arise so *expect* to spend a lot
of time scratching your head and concentrating hard to understand what
is going on.


as for reading the source code for the standard library: do. I do
from time to time. both to find out how things work and for
inspiration.

-Bjørn
 
B

Bjorn Borud

["Al Koch" <[email protected]>]
|
| It is certainily "comforting" to assume that a static method will
| only manipulate local variables.

....if the code was written by someone competent. which, of course,
you should not gamble on :).

| Or more strongly, assume that a static method doesn't, in itself,
| create a thread-unsafe situation but without a lot of experience
| with Java threads I would not know that your statement above is in
| itself "reasonable".

nope, it isn't reasonable. it would be reasonable to expect a
reasonable programmer to ensure static methods are thread-safe or
document issues that might arise in a multi-threaded scenario, but it
would be unreasonable to expect that all programmers are indeed
reasonable.

| The sense I'm getting from this and some other threads is that Java
| has matured to the point that your position is probably fine.
| Thanks for helping me get these issues into the proper perspective.

I'd like to recommend this book:

http://www.oreilly.com/catalog/jthreads3/

I recently read it and I'd recommend it to a broad spectrum of both
experienced and inexperienced programmers. (there's also a book
called "Concurrent Programming in Java" by Doug Lea, but this is a bit
dated, somewhat inaccessible to the beginner -- and...well, a bit
boring. though it should be mentioned that Doug did a great job with
the JSR 166 code. Thanks Doug, I use your code every day!)

-Bjørn
 
A

Al Koch

Hi Ray,
In general, I would assume that static methods are thread safe. Any
static method that is not would be considered to be broken by any
reasonable software engineer.

It is certainily "comforting" to assume that a static method will only
manipulate local variables. Or more strongly, assume that a static method
doesn't, in itself, create a thread-unsafe situation but without a lot of
experience with Java threads I would not know that your statement above is
in itself "reasonable". The sense I'm getting from this and some other
threads is that Java has matured to the point that your position is probably
fine. Thanks for helping me get these issues into the proper perspective.

Al,
(e-mail address removed)
 
A

Al Koch

Hi Bjorn,
the documentation should always say something about the thread safety
issues a class might have. (although I'd be the first to admit that I
often forget to document this myself unless it is some API that is
meant to be exposed to other developers).

I'm glad that you agree with me on this point. Part of the issue I'm been
raising is Sun's apparent failure to do this, leaving developer's with a
much greater level of uncertainity (and workload!) about what they do or do
not have to worry about!
it being static doesn't necessarily imply it has to manipulate static
variables.

Yes, I see that what I was concerned about is not necessarily true and in
fact if it is one might argue that the API is seriously flawed (and any
problems have probably already been discovered).

| If my thread is in the middle of executing createImageInputStream()
| and another thread enters this function don't I need to be
| concerned?

there are four ways for an API author to handle this:

- ensure the method doesn't alter any state or depend on any
state that could be changed by another thread.

- declare the method synchronized, thereby implying it does alter or
depend on state and saying what is used for synchronization

- do explicit synchronization inside the method

- not do any synchronization and document its thread safety
issues if they exist

all of them are valid ways of handling the same problem and what you
choose is mostly decided by how you intend the code to be used and
what your tastes are.

Yes, but again my point has been that in the absence of Sun doing any of the
above in so much of their API docs we *just don't know*!
it takes a a while to develop a proper understanding of concurrent
programming and the issues that often arise so *expect* to spend a lot
of time scratching your head and concentrating hard to understand what
is going on.


as for reading the source code for the standard library: do. I do
from time to time. both to find out how things work and for
inspiration.

Thanks for the comments - they help me get a proper perspective on the
issues.

Al,
(e-mail address removed)
 
B

blmblm

["Al Koch" <[email protected]>]
|
| It is certainily "comforting" to assume that a static method will
| only manipulate local variables.

...if the code was written by someone competent. which, of course,
you should not gamble on :).

| Or more strongly, assume that a static method doesn't, in itself,
| create a thread-unsafe situation but without a lot of experience
| with Java threads I would not know that your statement above is in
| itself "reasonable".

nope, it isn't reasonable. it would be reasonable to expect a
reasonable programmer to ensure static methods are thread-safe or
document issues that might arise in a multi-threaded scenario, but it
would be unreasonable to expect that all programmers are indeed
reasonable.

The example that occurred to me of a static method that would need
some attention in order to be thread-safe is Math.random(). But
the API documentation seems to be pretty explicit about the issues
(and even suggests what might be a better alternative if one is
doing multi-threaded programming).

I guess we can't be sure Sun has always managed to document the
parts of the API that need documenting w.r.t. thread safety, but
they're batting 1.000 on the two examples I've checked so far. :)?

[ snip ]
 
A

Al Koch

Hi Bjorn
I'd like to recommend this book:

http://www.oreilly.com/catalog/jthreads3/

I recently read it and I'd recommend it to a broad spectrum of both
experienced and inexperienced programmers. (there's also a book
called "Concurrent Programming in Java" by Doug Lea, but this is a bit
dated, somewhat inaccessible to the beginner -- and...well, a bit
boring. though it should be mentioned that Doug did a great job with
the JSR 166 code. Thanks Doug, I use your code every day!)

Thanks much for the recommendation. The info on the O'Reilly suggest that
this would eb a good book to get!

Al,
(e-mail address removed)
 
A

Al Koch

Hi BL,
The example that occurred to me of a static method that would need
some attention in order to be thread-safe is Math.random(). But
the API documentation seems to be pretty explicit about the issues
(and even suggests what might be a better alternative if one is
doing multi-threaded programming).

I guess we can't be sure Sun has always managed to document the
parts of the API that need documenting w.r.t. thread safety, but
they're batting 1.000 on the two examples I've checked so far. :)?

Yes, Sun did say something here about this static method but look at
IOImage. They don't say anything here so we are left to either 1) try to
guess whether there is a problem which seems to me to be dangerous or 2) go
to the extra effort to obtain and read the code which sure is a lot of work
that could be avoided of we just had a clear statement one way or another.

AL,
(e-mail address removed)
 
B

blmblm

Hi Bjorn


Thanks much for the recommendation. The info on the O'Reilly suggest that
this would eb a good book to get!

This doesn't help you now, but inside sources tell me that Doug Lea
and several other people are working on a new book that they think
will be out in December; it's not an update to or a follow-on to
"Concurrent Programming in Java" but instead something aimed more
at working programmers (if I understand it right). Working title
is "Java Concurrency in Practice". "FYI", as they say.
 
B

blmblm

Hi BL,


Yes, Sun did say something here about this static method but look at
IOImage. They don't say anything here so we are left to either 1) try to
guess whether there is a problem which seems to me to be dangerous or 2) go
to the extra effort to obtain and read the code which sure is a lot of work
that could be avoided of we just had a clear statement one way or another.

Sure. But it seems to me that it's reasonable to assume, in the
absence of explicit documentation one way or another, that nonstatic
methods operating on objects that could reasonably be assumed to
have nontrivial internal state are not thread-safe. Now that I
think about, something similar may apply to static methods as well,
except the internal state is represented by class variables rather
than instance variables.

Neither guessing nor reading source code is a perfect solution
(and as a former math major I also have a bias against imperfect
solutions), but I strongly suspect that educated guessing will work
often enough for it to be "good enough" in almost all practical
contexts.
 
B

blmblm

Sure. But it seems to me that it's reasonable to assume, in the
absence of explicit documentation one way or another, that nonstatic
methods operating on objects that could reasonably be assumed to
have nontrivial internal state are not thread-safe. Now that I
think about, something similar may apply to static methods as well,
except the internal state is represented by class variables rather
than instance variables.

I meant to add: And for the specific example you mention (IOImage),
I would assume nontrivial internal state and code accordingly (i.e.,
doing my own synchronization if accessing an IOImage from multiple
threads).
 
B

Bjorn Borud

[[email protected]]
|
| This doesn't help you now, but inside sources tell me that Doug Lea
| and several other people are working on a new book that they think
| will be out in December; it's not an update to or a follow-on to
| "Concurrent Programming in Java" but instead something aimed more
| at working programmers (if I understand it right). Working title
| is "Java Concurrency in Practice". "FYI", as they say.

that is great news! wonder if I can pre-order it on Amazon.com

-Bjørn
 
B

Bjorn Borud

[Bjorn Borud <[email protected]>]
| [[email protected]]
| |
| | This doesn't help you now, but inside sources tell me that Doug Lea
| | and several other people are working on a new book that they think
| | will be out in December; it's not an update to or a follow-on to
| | "Concurrent Programming in Java" but instead something aimed more
| | at working programmers (if I understand it right). Working title
| | is "Java Concurrency in Practice". "FYI", as they say.
|
| that is great news! wonder if I can pre-order it on Amazon.com

turns out: one can, so I did:

http://www.amazon.com/exec/obidos/tg/detail/-/0321349601

interesting list of authors.

-Bjørn
 
A

Al Koch

Hi B.L.,

Thanks for all of your helpful comments and also for the book reference in
your other "sub-thread" on this thread.

Al.
(e-mail address removed)
 
T

Thomas G. Marshall

(e-mail address removed) coughed up:
Everyone following this discussion should be aware that there's a
parallel (no pun intended) discussion with the same subject line going
on in comp.java.lang.help. I'm going to try to cross-post this reply
so people who follow both groups will get this ....

Others are posting a lot of useful information. You might also find
the following two links useful, if you haven't already come across
them. (These were the most useful-seeming of the first few that
popped up on a Google search for "not thread safe" and "Java".)

http://www-128.ibm.com/developerworks/java/library/j-threads1.html


Coincidentally, this article uses nearly the same MT-unsafe example I use:

There's says this:

<quote>
private int foo;
public synchronized int getFoo() { return foo; }
public synchronized void setFoo(int f) { foo = f; }

If a caller wants to increment the foo property, the following code to
do so is not thread-safe:
...
setFoo(getFoo() + 1);
</quote>

This example should be among the very first ever given. I've already given
this example in the .help version of this thread. It is the most common
mistake I've seen in MT programming.

IMO, it's because users often read the code as if it is in this order
(sounds it in their heads):

Set
with the Get
plus 1

.....which seems as if the lock is aquired at the set and all is well.

But the code (of course) is really ordered as this:

Get the value
add 1
Set the value

which forms a compound operation.
 
T

Thomas G. Marshall

John Currier coughed up:
The note doesn't mention that the synchronized collection wrappers'
Iterators aren't thread-safe...you've got to synchronize on the
wrapper if you need thread-safe access to the collection via an
iterator.


Just as you have to synchronize on the wrapper to do *ANY* compound
operation in a thread safe manner.
 
T

Thomas G. Marshall

Dale King coughed up:
You seem to have a lot to learn about what it really means to be
"thread safe". Yes most of the API is not thread safe in that it is
not safe for multiple threads to be calling methods on an instance
without some sort of synchronization mechanism. That is not a bad
thing.
Right!


Thread safety does not begin and end with the Java API. Even if every
method in the Java API were synchronized that would not in and of
itself guarantee much of anything about the thread safety of any
program that used those API's. Thread safety involves how an API is
used as well.


Yes! I really wish more people would state this more often. There seems to
be a prevailing notion, even among senior engineers sometimes, that
synchronizing all the methods of a class makes any compound operation done
to that object thread safe.


....[rip]...
 
T

Thomas G. Marshall

Raymond DeCampo coughed up:

....[rip]...
In general, I would assume that static methods are thread safe. Any
static method that is not would be considered to be broken by any
reasonable software engineer.


But that would be a dangerous assumption to make.

A static method can easily be MT unsafe. Static methods usually manipulate
one or more class variables, and those could be mucked up just as easily as
[object] member variables can.

....[rip]...
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top