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

A

Al Koch

Hello,

I am writing a Java servlet and am new to coding for thread synchronization.
I suspect that there must be an "obvious" solution to the following problem
but after sevearl days of research I can't find it!

It is my understanding that, in general, the J2SE 1.4 API is *not*
thread-safe. There are some APIs where the Sun documentation states that a
Class's methods are thread-safe (such as StringBuffer) but in general, most
of the text and web search references I have found have stated that the API
in general is not thread-safe. That means that there must be at least one
(and it's probably most) API that is not thread-safe and let me just call
such an unsafe method "UnsafeAPI()". My question is, how do I use
UnsafeAPI() and write code to make my code thread-safe?

For example, if I have the following code:

public final class MyClass {
private int i;
private int j;
private int k;

public finale void MyMethod(int i, int j, int k)
{
this.i = i;
this.j = j;
this.k = k;
}
}

I have a thread safety issue here. Assignement to an int is atomic so no
one of the three assignment statements in MyMethod() can be interrupted by
another thread. However, the *sequence of all three assignments* certainly
can be interrupted so I am vulnerable to a synchronization issue. I could
either fix this proiblem by adding the "sychronized" modifier to the
MyMethod declaration, or I could do the following:


public final class MyClass {
private int i;
private int j;
private int k;

public finale void MyMethod(int i, int j, int k)
{
synchronize(this) {
this.i = i;
this.j = j;
this.k = k;
}
}
}

At this point I am thread safe. However, assume that I also need to call
UnsafeAPI(). Now my code looks like:

public final class MyClass {
private int i;
private int j;
private int k;

public finale void MyMethod(int i, int j, int k)
{
synchronize(this) {
this.i = i;
this.j = j;
this.k = k;
UnsafeAPI(); // this is any J2SE 1.4 API that, in general, is not
thread safe!
}
}
}

The synchronize(this) guarantees that no other thread can enter *my code
block* in MyMethod() but (as far as I can tell) it in no way prevents
another thread from entering UnsafeAPI() from another block of code, either
in my servlet or even in another application altogether.

There must be some way to block a thread from entering UnsafeAPI() because
otherwise it would be impossible to write a thread safe application, but I
sure can't find a way to do this. Can someone explain how this is done? If
you can also tell me how/where you learned how to do this I would be very
interested because I can't locate any such information!)

Thank you!
Al

(e-mail address removed)
 
C

Chris Head

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Al Koch wrote:
[snip]
The synchronize(this) guarantees that no other thread can enter *my code
block* in MyMethod() but (as far as I can tell) it in no way prevents
another thread from entering UnsafeAPI() from another block of code, either
in my servlet or even in another application altogether.

There must be some way to block a thread from entering UnsafeAPI() because
otherwise it would be impossible to write a thread safe application, but I
sure can't find a way to do this. Can someone explain how this is done? If
you can also tell me how/where you learned how to do this I would be very
interested because I can't locate any such information!)

Thank you!
Al

(e-mail address removed)

Hello,
It is true that most of the Java API is not thread-safe. However, it is
ALSO true that most of the Java API is implemented as member functions
in classes. Thus, your example of UnsafeAPI() would probably be a member
function on a class. Generally, while it is NOT safe to call UnsafeAPI()
multiple times simultaneously on the SAME instance of the class, it IS
safe to call it simultaneously on DIFFERENT INSTANCES. At this point,
you must realize that your own application probably has essentially
complete control of the specific object you're interested in, so it's
fairly feasible to synchronize those calls.

If you will be calling methods on an object of a given API class from
various of your own objects in various of your own threads, it might be
better to synchronize on the object of the API class rather than on
"this". That way calls to the API object from different of your own
objects will all be serialized against each other (and become safe).

For example:

class MyA {
UnsafeAPIObject obj;
MyA(UnsafeAPIObject o) {
obj = 0;
}
public doSomething() {
synchronized(obj) {
obj.doStuff();
}
}
}

class MyB {
UnsafeAPIObject obj;
MyB(UnsafeAPIObject o) {
obj = 0;
}
public doSomething() {
synchronized(obj) {
obj.doStuff();
}
}
}

....

UnsafeAPIObject obj = new UnsafeAPIObject();
MyA a = new MyA(obj);
MyB b = new MyB(obj);
a.doSomething();
<in some other thread>
b.doSomething();

Here, the obj.doStuff() calls will be properly synchronized. Had you
replaced both synchronized(obj) blocks with synchronized(this), you
would have had no synchronization, because thread 1 would sync on (a)
and thread 2 would sync on (b), so they would not block each other. I
believe it's generally recommended to synchronize on the object you're
calling as a convention.

Hope this clears things up (and that I haven't said anything too wrong)

Chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (MingW32)

iD8DBQFCuNL+gxSrXuMbw1YRAoVhAJ9k5O12TzFUweVs0eiSFCTTltADhQCcCf3r
GFmvh7D4UjJRKByL9gscOZ4=
=ROSq
-----END PGP SIGNATURE-----
 
A

Al Koch

Hi Chris,

Thanks very much for your reply. I have a couple of follow on questions.
Here, the obj.doStuff() calls will be properly synchronized. Had you
replaced both synchronized(obj) blocks with synchronized(this), you
would have had no synchronization, because thread 1 would sync on (a)
and thread 2 would sync on (b), so they would not block each other. I
believe it's generally recommended to synchronize on the object you're
calling as a convention.

I didn't state it in my question but I agree that "most of the time" the API
would be called on an instance of a "Java API class" and I suspected that I
ought to be able to synch control of my object instances (I didn't want to
say that in the question so that I could get a "wide open" response.)
However, there are (at least!) two things that confuse me:

1) How "safe" is the new operator? Here is a (simplifed) piece of code:

public static final String appendTrailingBackslash(String sStr)
{
sbStr = new StringBuffer(sStr);
sbStr.append('\\');
return(sbStr.toString());
}

Do I ever need to worry about synch'ing the new and if so, how would I do
that in the above example. For instance, the following wouldn't accomplish
anything (assuming it is even necesarry to protect the new):

public static final String appendTrailingBackslash(String sStr)
{
Object lockObject = new Integer(666);
StringBuffer sbStr = null;
synchronized(lockObject) {
sbStr = new StringBuffer(sStr);
}
sbStr.append('\\');
return(sbStr.toString());
}


2) We agree that I should be able to synch my object instances but what
about a static member function in the API. For example,

MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");

In this example, getInstance() is a static member. How in the world do you
protect this call? (I realize that one might argue that getInstance()
"appears" to only "lookup" something and as such needs no synchronization
but 1) how are we supposed to determine what a static member function does
internally and 2) if we have a static member function that we do need to
worry about, how would that be protected?)

Thanks again for your help.

Al.
(e-mail address removed)
 
E

Eric Sosman

Al said:
Hi Chris,

Thanks very much for your reply. I have a couple of follow on questions.

Here, the obj.doStuff() calls will be properly synchronized. Had you
replaced both synchronized(obj) blocks with synchronized(this), you
would have had no synchronization, because thread 1 would sync on (a)
and thread 2 would sync on (b), so they would not block each other. I
believe it's generally recommended to synchronize on the object you're
calling as a convention.

I didn't state it in my question but I agree that "most of the time" the API
would be called on an instance of a "Java API class" and I suspected that I
ought to be able to synch control of my object instances (I didn't want to
say that in the question so that I could get a "wide open" response.)
However, there are (at least!) two things that confuse me:

1) How "safe" is the new operator? Here is a (simplifed) piece of code:

public static final String appendTrailingBackslash(String sStr)
{
sbStr = new StringBuffer(sStr);
sbStr.append('\\');
return(sbStr.toString());
}

Do I ever need to worry about synch'ing the new [...]

No, it's not necessary to synchronize the `new' operator.
You probably need to synchronize access to `sbStr', which seems
to be a static member of the class containing this method --
but maybe that was just a typo.
2) We agree that I should be able to synch my object instances but what
about a static member function in the API. For example,

MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");

In this example, getInstance() is a static member. How in the world do you
protect this call? (I realize that one might argue that getInstance()
"appears" to only "lookup" something and as such needs no synchronization
but 1) how are we supposed to determine what a static member function does
internally and 2) if we have a static member function that we do need to
worry about, how would that be protected?)

There's no effective way to synchronize access to an
accessible static method -- you could synchronize on the
method's class or on any other agreed-upon object, but you'd
need to rely on all callers doing the synchronization, which
is hard to enforce.

Perhaps the JavaDoc should explicitly say "getInstance()
is safe to use in multi-threaded code," but I think we can
probably take that for granted. If the static method operates
on thread-unsafe objects, the method itself should take care
of synchronizing appropriately. For example, a static factory
method that maintains a cache of frequently-used objects may
need to synchronize its own access to the cache, but the caller
of the factory method shouldn't need to worry.

The idea in Java is to protect the object, not the code.
(Disclaimer: Some months back there was a heated discussion of
this point, and somebody took exception to this view of things.
Of course, *he* was wrong.) If you think about the object
being manipulated rather than about the code that does the
manipulations, things may be a lot less confusing -- and maybe
even less threatening.
 
A

Al Koch

Hi Eric,

Thanks for your response.
No, it's not necessary to synchronize the `new' operator.
You probably need to synchronize access to `sbStr', which seems
to be a static member of the class containing this method --
but maybe that was just a typo.
Yes, that was a typo; the code example should have shown sbStr as being
declared as a local variable (which would make it it thread-safe, right?).
You say that I don't need to synchronize the new opertaor. Can you tell me
how you know this? I am not asking that question because I don't believe
you but rather because I'm trying to find that "magic reference" that
answers such questions! It seems that what I am asking is so fundamental
("what in the Java language and the J2SE API is thread-safe and how does a
person know?") that the answer could be found in a hundred places but it
seems like this question is one that no book or support site wants to deal
with! So, how did you learn that the new operator is safe?
There's no effective way to synchronize access to an
accessible static method -- you could synchronize on the
method's class or on any other agreed-upon object, but you'd
need to rely on all callers doing the synchronization, which
is hard to enforce.

Assuming for the moment that I'll depend on "evryone else" enforcing
synchronization (which, since that means every other piece of Java code
running in the same VM that I'm in, is silly!), how would I "synchronize on
the method's class"? Using the example that I presented, how would you
synchronize the following:

MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");

Would it be:

MessageDigest dummyDigestObject = new MessageDigest;
synchronize(dummyDigestObject) {
MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");
}
Perhaps the JavaDoc should explicitly say "getInstance()
is safe to use in multi-threaded code," but I think we can
probably take that for granted. If the static method operates
on thread-unsafe objects, the method itself should take care
of synchronizing appropriately. For example, a static factory
method that maintains a cache of frequently-used objects may
need to synchronize its own access to the cache, but the caller
of the factory method shouldn't need to worry.

You are suggesting that we infer what the code is doing and that we can take
for granted that the API is doing what needs to be done to protect the code.
This is similar to a variety of posts that I've come across in a wide number
of forums that expressive a great deal of frustration that the
documentation is silent on so much of this. What you are saying is in line
with much that I've read but (acknowleding that I'm still new to dealing
with Threads in Java) this seems like a rather unsuitable way to go about
building software! You aren't expressing much concern that this is all
rather undocumented; can you help me understand why (if I am reading between
the lines correctly) this isn't an issue of much concern for you?
The idea in Java is to protect the object, not the code.
(Disclaimer: Some months back there was a heated discussion of
this point, and somebody took exception to this view of things.
Of course, *he* was wrong.) If you think about the object
being manipulated rather than about the code that does the
manipulations, things may be a lot less confusing -- and maybe
even less threatening.

That seems like a helpful "guiding principle".

Thanks again for your comments.

Al.
(e-mail address removed)
 
E

Eric Sosman

Al said:
Hi Eric,

Thanks for your response.



Yes, that was a typo; the code example should have shown sbStr as being
declared as a local variable (which would make it it thread-safe, right?).
You say that I don't need to synchronize the new opertaor. Can you tell me
how you know this? I am not asking that question because I don't believe
you but rather because I'm trying to find that "magic reference" that
answers such questions! It seems that what I am asking is so fundamental
("what in the Java language and the J2SE API is thread-safe and how does a
person know?") that the answer could be found in a hundred places but it
seems like this question is one that no book or support site wants to deal
with! So, how did you learn that the new operator is safe?

`new' itself is safe for the same reason `+' is safe:
it's just an operator; it has no internal state of its own
that needs protection.

It's possible to write an unsafe constructor, but that's
a somewhat different matter. If a constructor is unsafe there's
really not much you can do about it; constructors are a lot like
static methods in this regard. However, I can think of only two
ways a constructor can be unsafe (perhaps the experts will chime
in with more):

- While building the new object, the constructor could
manipulate some other object that could be accessible
to another thread. For example, a constructor that
maintained a "registry" of constructed instances might
manipulate the registry without synchronizing. I'd
consider this a bug in the constructor.

- The constructor could put a reference to the new object
someplace where another thread could find it, and then
proceed to manipulate the new object without synchronizing.
Again, I'd consider this a constructor bug.

The typical constructor that just massages the object under
construction and doesn't export any references to it is safe
because it's working on an object that no other thread can
(yet) get hold of.
Assuming for the moment that I'll depend on "evryone else" enforcing
synchronization (which, since that means every other piece of Java code
running in the same VM that I'm in, is silly!), how would I "synchronize on
the method's class"? Using the example that I presented, how would you
synchronize the following:

MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");

Would it be:

MessageDigest dummyDigestObject = new MessageDigest;
synchronize(dummyDigestObject) {
MessageDigest mdSHA1 = MessageDigest.getInstance("SHA-1");
}

Any agreed-upon object would do, so long as all the, um,
"synchronizers" have access to it. Your example as written
won't work (no parameters to the constructor, and besides: the
MessageDigest constructor is protected), but could be made to
work. You'd still have something of a problem, though: if
you're trying to ensure that only one thread at a time executes
getInstance() you need to have them all synchronize on the same
object; just creating and discarding a new one each time won't
do the trick. That means you need an object that's "visible"
to all the threads, not a thread-unique object for each of them.

Any agreed-upon object would do, as I said before. You might
choose System.out or Runtime.getRuntime() or "BALDERDASH". The
conventional choice when there's really nothing better is to use
the Class object for the class to which the method belongs, in
this case `MessageDigest.class'.
You are suggesting that we infer what the code is doing and that we can take
for granted that the API is doing what needs to be done to protect the code.
This is similar to a variety of posts that I've come across in a wide number
of forums that expressive a great deal of frustration that the
documentation is silent on so much of this. What you are saying is in line
with much that I've read but (acknowleding that I'm still new to dealing
with Threads in Java) this seems like a rather unsuitable way to go about
building software! You aren't expressing much concern that this is all
rather undocumented; can you help me understand why (if I am reading between
the lines correctly) this isn't an issue of much concern for you?

What I'm saying -- although I don't think it's written down
explicitly -- is that thread-safety is the "default assumption"
for Java classes. BigInteger.valueOf(long) doesn't come right
out and say that it's thread-safe, but I'm willing to assume it
is even though it quite possibly manipulates a static cache.
The practice in JavaDoc seems to be to highlight the things that
are *not* thread-safe -- take a look at ArrayList, for example --
rather than to note all the things that are. (I have to admit,
though, that the opposite sometimes happens; see StringBuffer
for an example.)

Here's a final thought: `synchronized' does not in and of
itself guarantee thread safety. We've all learned that Vector
is synchronized, but the following is thread-unsafe anyhow:

Vector v = getSomeVector();
for (int i = 0; i < v.size(); ++i)
System.out.println(v.get(i));

See the problem? size() is safe and get() is safe, but that
doesn't mean that the combined operation of size() followed by
get() is safe. Just after this thread receives a value from
size() a second thread could leap in and run clear() on the
Vector before the first thread makes its call to get(), and
you'd get an ArrayIndexOutOfBoundsException. You could fix
the code this way:

Vector v = getSomeVector();
synchronized (v) {
for (int i = 0; i < v.size(); ++i)
System.out.println(v.get(i));
}

or if you didn't want to hold the lock for the entire loop you
could write

Vector v = getSomeVector();
for (int i = 0; ; ++i) {
synchronized (v) {
if (i < v.size())
System.out.println(v.get(i));
else
break;
}
}

(although one might wonder whether this particular example
makes a whole lot of sense).
 
J

John Currier

public static final String appendTrailingBackslash(String sStr)
{
Object lockObject = new Integer(666);
StringBuffer sbStr = null;
synchronized(lockObject) {
sbStr = new StringBuffer(sStr);
}

sbStr.append('\\');
return(sbStr.toString());
}

It looks like you're trying to complicate things tremendously. There
is nothing in this method that can be referenced by another thread
other than possibly aStr, which is immutable. The method (actually
more of a function) is thread safe without any form of synchronization.
It can, of course, be replaced with String's "+" operator.

John
 
A

Al Koch

Hi Eric,

Again thanks for taking the time to write such an extensive reply. If
others find this thread (no pun intended!) I'm sure they will benefit from
all this!
`new' itself is safe for the same reason `+' is safe:
it's just an operator; it has no internal state of its own
that needs protection.

OK, and you anticipated exactly what worried me about new. Yes, it's "just
an operator" but it triggers a Ctor that does who knows what, but that's
what you address next!

It's possible to write an unsafe constructor, but that's
a somewhat different matter. If a constructor is unsafe there's
really not much you can do about it; constructors are a lot like
static methods in this regard. However, I can think of only two
ways a constructor can be unsafe (perhaps the experts will chime
in with more):

Good point; I'd hope that we can assume that any Ctor "thread errors" in
J2SE/EE would have popped up by now so I'll stop worrying about that one!

What I'm saying -- although I don't think it's written down
explicitly -- is that thread-safety is the "default assumption"
for Java classes. BigInteger.valueOf(long) doesn't come right
out and say that it's thread-safe, but I'm willing to assume it
is even though it quite possibly manipulates a static cache.
The practice in JavaDoc seems to be to highlight the things that
are *not* thread-safe -- take a look at ArrayList, for example --
rather than to note all the things that are. (I have to admit,
though, that the opposite sometimes happens; see StringBuffer
for an example.)

I'd like to accept your statement that "thread-safety is the "default
assumption"" since that eliminates a lot of things to worry about but what
worries me is that I've come across an overwhelming number of posts in all
sorts of forums where the sentiment that was expressed was that we should
assume that the API is *not* thread-safe unless it states that it is (such
as StringBuffer does). Given so much conflicting opinion on this can you
speculate on why Sun hasn't come out with some sort of definitive statement
on this? Since thread safety is *essential* (at least in a multi-threaded
environment which is so much of where Java is used such as servlets and Web
Services apps), why would Sun allow such confusion to exist? If the API is
thread-safe why not just say so? Their failure to make such a statement
causes me to be concerned that it isn't.

Here's a final thought: `synchronized' does not in and of
itself guarantee thread safety. We've all learned that Vector
is synchronized, but the following is thread-unsafe anyhow:

Vector v = getSomeVector();
for (int i = 0; i < v.size(); ++i)
System.out.println(v.get(i));

See the problem? size() is safe and get() is safe, but that
doesn't mean that the combined operation of size() followed by
get() is safe. Just after this thread receives a value from
size() a second thread could leap in and run clear() on the
Vector before the first thread makes its call to get(), and
you'd get an ArrayIndexOutOfBoundsException. You could fix
the code this way:

Yes, good point and by "thread-safe" I haven't meant that any place or way
that a thread-safe API is used is therefore thread-safe. I meant that any
Class or other "external" resources used within the API are synchronized.

As a summary, let me restate what I am confused and concerned about. Here
is my reasoning:

1) There is much concern on the Web that the J2SE API is not thread-safe.
If we choose to assume this...
2) There is at least Class, call it UnsafeClass, that has at least one
method, call it UnsafeAPI() that is not thread-safe, therefore ...
3) There is either a Class variable in UnsafeClass, or UnsafeAPI() has an
instance variable or there is some "external" resource such as a file,
database connection, socket, etc. that is not synchronized by UnsafeAPI() .
(If this were not true then UnsafeAPI() *would be* thread-safe!).

We can ignore the case where it is an instance variable that is unprotected
because if I have an instance of UnsafeClass I can just code
synchronize("instance of UnsafeClass") {
UnsafeAPI(
}
and all should be well.

That leaves us with those cases where there is an unprotected Class variable
or an unprotected external resource. I guess my question boils down to, how
do I use UnsafeAPI() so that my code is thread-safe? Code like
synchronize("instance of some Class other than UnsafeClass") {
UnsafeAPI();
}

will not work because, while it will protect me from all threads that run
thru my code where I've been sure to always synch on "instance of some Class
other than UnsafeClass", this provides no protection from some other app
running in the JVM from just making its own call to UnsafeAPI() while my
thread is in there!

Am I correct in concluding that as long as I need to use an "UnsafeAPI()"
that there is simply no way to protect my code? I guess that is what you
stated above when you said "There's no effective way to synchronize access
to an accessible static method". As long as any other app running in the
JVM can call "UnsafeAPI()", even if that programmer wanted to synch on
something, it's a crapshoot as to whether or not he wrote
synchronize("UnsafeClass.class") {
UnsafeAPI(
}

The conclusion I just drew, IMO, puts us all in an unacceptable situation.
As long as there is no way to assure synchrinization when using API's in the
J2SE/EE it seems that all (threaded) code has a big vulnerability. That
brings me back to your feeling that the API is thread-safe. If so, why in
the world doesn't Sun take a position in this? Arggghhhh!

Thanks much - this is a very valuable discussion,
Al.
(e-mail address removed)
 
A

Al Koch

Hi John,

Thanks for the reply.
It looks like you're trying to complicate things tremendously. There
is nothing in this method that can be referenced by another thread
other than possibly aStr, which is immutable. The method (actually
more of a function) is thread safe without any form of synchronization.
It can, of course, be replaced with String's "+" operator.

Yes, my example was a bit "contrived". The problem I have is that (since I
am still new to threads in Java) I haven't yet come across an API that I can
show is causing a problem, but please review the following and see if it
makes sense.

1) There is much concern on the Web that the J2SE/EE API is not thread-safe.
In researching this I have come across a large number of threads (no pun
intended) in a variety of forums and the great majority express the belief
that the J2SE/EE API is not, unless it states otherwise, thread-safe. As
far as I can tell, Sun has not stated that it is thread-safe and that in
itself makes me suspect that it isn't. If we choose to assume that it is
not, in general, thread-safe...
2) There is at least one Class, call it UnsafeClass, that has at least one
method, call it UnsafeAPI() that is not thread-safe, therefore ...
3) There is either a Class variable in UnsafeClass, or UnsafeAPI() has an
instance variable or there is some "external" resource such as a file,
database connection, socket, etc. that is not synchronized by UnsafeAPI() .
(If this were not true then UnsafeAPI() *would be* thread-safe!).

We can ignore the case where it is an instance variable that is unprotected
because if I have an instance of UnsafeClass I can just code
synchronize("instance of UnsafeClass") {
UnsafeAPI()
}
and all should be well.

That leaves us with those cases where there is an unprotected Class variable
or an unprotected external resource. I guess my question boils down to, how
do I use UnsafeAPI() so that my code is thread-safe? Code like
synchronize("instance of some Class other than UnsafeClass") {
UnsafeAPI();
}

will not work because, while it will protect me from all threads that run
thru my code where I've been sure to always synch on "instance of some Class
other than UnsafeClass", this provides no protection from some other app
running in the JVM from just making its own call to UnsafeAPI() while my
thread is in there!

Am I correct in concluding that as long as I need to use an "UnsafeAPI()"
that there is simply no way to protect my code? As long as any other app
running in the JVM can call "UnsafeAPI()", even if that programmer wanted to
synch on something, it's a crapshoot as to whether or not he used what might
be the "obvious" object to synch on as in
synchronize("UnsafeClass.class") {
UnsafeAPI(
}


The conclusion I just drew, IMO, puts us all in an unacceptable situation.
As long as there is no way to assure synchronization when using API's in the
J2SE/EE it seems that all (threaded) code has a big vulnerability. If this
is not so, do you have any idea why in the world doesn't Sun take a position
on this?

Thanks much,
Al.
(e-mail address removed)
 
J

John Currier

The vast majority of "not thread safe" code is thread safe at the class
level (i.e., it doesn't contain "unprotected" static members) but not
at the instance level.

Take SimpleDateFormat as an example. A single instance of
SimpleDateFormat can't be used by multiple threads safely. The
instance modifies its internal state during an invocation, so one
thread can easily change another thread's results.

The solution? Don't let multiple threads access that instance of the
class. If you write a class that has a SimpleDateFormat instance
variable and you want instances of your class to be thread safe then
you'll need to wrap the formatter in a synchronized block.

SimpleDateFormat *is* safe at the class level. That is, multiple
threads can access their own instance of SimpleDateFormat without
having to worry about somehow only allowing one thread into any
instance of the class at a time.

Hope this helps,
John
http://schemaspy.sourceforge.net
 
B

blmblm

Hi Eric,

Again thanks for taking the time to write such an extensive reply. If
others find this thread (no pun intended!) I'm sure they will benefit from
all this!

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

http://www-106.ibm.com/developerworks/java/library/j-jtp09263.html

Some classes are pretty explicit about thread-safety issues -- I checked
ArrayList and found the following:

Note that this implementation is not synchronized. If multiple threads
access an ArrayList instance concurrently, and at least one of the
threads modifies the list structurally, it must be synchronized
externally. (A structural modification is any operation that adds or
deletes one or more elements, or explicitly resizes the backing array;
merely setting the value of an element is not a structural
modification.) This is typically accomplished by synchronizing on some
object that naturally encapsulates the list. If no such object exists,
the list should be "wrapped" using the Collections.synchronizedList
method. This is best done at creation time, to prevent accidental
unsynchronized access to the list:
List list = Collections.synchronizedList(new ArrayList(...));

which seems pretty clear.

But it's not clear that all classes are so well documented, and this
is an interesting point I hadn't been aware of ....
 
C

Chris Head

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Al Koch wrote:
[snip]
Am I correct in concluding that as long as I need to use an "UnsafeAPI()"
that there is simply no way to protect my code? I guess that is what you
stated above when you said "There's no effective way to synchronize access
to an accessible static method". As long as any other app running in the
JVM can call "UnsafeAPI()", even if that programmer wanted to synch on
something, it's a crapshoot as to whether or not he wrote
synchronize("UnsafeClass.class") {
UnsafeAPI(
}
[snip]


Just to clarify:
When he said UnsafeClass.class, he meant UnsafeClass.class, not
"UnsafeClass.class".

As in:

synchronized(UnsafeClass.class) {
UnsafeClass.UnsafeAPI();
}

This is actually a legal expression. It returns an object of type
java.lang.Class representing UnsafeClass. THIS object is what
synchronized static methods implicitly synchronize on. There is only one
such object for each class per classloader.

Also, I would suggest not synchronizing on strings because it's too easy
to make a typo and the compiler won't catch it for you.

Chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (MingW32)

iD8DBQFCuuZSgxSrXuMbw1YRAtSyAKCJFkRi3t/PtF4DINTmO84KZUBRXwCbBO43
B0HnbPtNvd5bLBOJfvrUM94=
=p1Eq
-----END PGP SIGNATURE-----
 
E

Eric Sosman

Al said:
[...] Given so much conflicting opinion on this can you
speculate on why Sun hasn't come out with some sort of definitive statement
on this?

Just in case you're reading more into my E-mail address
than is actually there: I do not speak for Sun Microsystems,
and I *definitely* do not speculate for Sun Microsystems!
I speak and speculate for myself; if you need "authoritative"
answers I'm not the source. Clear?
As a summary, let me restate what I am confused and concerned about. Here
is my reasoning:

1) There is much concern on the Web that the J2SE API is not thread-safe.

Well, that's just a special case of "There is much concern
on the Web that X," where X can be almost anything.
If we choose to assume this...
2) There is at least Class, call it UnsafeClass, that has at least one
method, call it UnsafeAPI() that is not thread-safe, therefore ...
3) There is either a Class variable in UnsafeClass, or UnsafeAPI() has an
instance variable or there is some "external" resource such as a file,
database connection, socket, etc. that is not synchronized by UnsafeAPI() .
(If this were not true then UnsafeAPI() *would be* thread-safe!).

As I tried to illustrate in my previous post, "thread-safe"
is not entirely cut-and-dried. It is possible to use a "thread-
safe" interface in unsafe ways. Even StringBuffer can be used
unsafely (the example I gave for Vector shows one way).
We can ignore the case where it is an instance variable that is unprotected
because if I have an instance of UnsafeClass I can just code
synchronize("instance of UnsafeClass") {
UnsafeAPI(
}
and all should be well.

No, not if someone other than you fails to follow this
discipline. It's not enough that *you* code this way; you've
got to get *everyone* to code this way.

One approach is to wrap the suspect object in a class of
your own that synchronizes and then delegates:

class ArmoredUnsafeClass {
private UnsafeClass obj = new UnsafeClass();
synchronized void UnsafeAPI() {
obj.UnsafeAPI();
}
}

See Collections.synchronizedCollection() for an example of a
slightly different way to get the same effect.
That leaves us with those cases where there is an unprotected Class variable
or an unprotected external resource. I guess my question boils down to, how
do I use UnsafeAPI() so that my code is thread-safe? Code like
synchronize("instance of some Class other than UnsafeClass") {
UnsafeAPI();
}

will not work because, while it will protect me from all threads that run
thru my code where I've been sure to always synch on "instance of some Class
other than UnsafeClass", this provides no protection from some other app
running in the JVM from just making its own call to UnsafeAPI() while my
thread is in there!

Well, if the "un-safety" involves only instance variables,
you can use ArmoredUnsafeClass instead of UnsafeClass. Other
code may be using UnsafeClass directly, but as long as it can
never get hold of a reference to one of your "armored" objects,
it can't bother you or be bothered by you.

If the "un-safety" involves (ab)use of a shared resource --
a network connection, say -- then you've got a bigger problem.
If UnsafeAPI() carries on an extended dialogue across a socket,
exchanging several messages with the peer, then two simultaneous
UnsafeAPI() invocations will probably garble both conversations.
You could synchronize on any convenient and agreed-upon object
(like UnsafeClass.class or the socket), but if there are chunks
of code not under your control you can't be sure you've found
all the bad spots or that somebody else won't introduce a new one.
But in a case like this I'd argue that either UnsafeClass is
broken (its implementor didn't think about thread safety) or that
it's being misused (there's some "natural" reason for having only
one thread use the API, and the application shouldn't be trying
to use it concurrently in the first place).
The conclusion I just drew, IMO, puts us all in an unacceptable situation.
As long as there is no way to assure synchrinization when using API's in the
J2SE/EE it seems that all (threaded) code has a big vulnerability. That
brings me back to your feeling that the API is thread-safe. If so, why in
the world doesn't Sun take a position in this? Arggghhhh!

As mentioned above, I don't speculate for Sun. I *do* think
you're worrying far too much; the existence and success of big
bundles of multi-threaded Java applications suggests that the
problems are not as severe as you seem to believe. Are you, by
any chance, old enough to remember Skylab helmets?
 
A

Al Koch

Hi BL,
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

http://www-106.ibm.com/developerworks/java/library/j-jtp09263.html

These are some good links - thanks for posting them!

Some classes are pretty explicit about thread-safety issues -- I checked
ArrayList and found the following: ,,,
But it's not clear that all classes are so well documented, and this
is an interesting point I hadn't been aware of ....

Yes, that's really my concern. This apears to be a difficulr area because
it seems that in the absence of Sun (or whoever is the JVM vendor) stating
that their implementation is "thread-safe except for ... " or "not
thread-safe except for ..." we are left with a really big burden, e.g., each
of us has to review the source for the API implementation, which is simply
not practical! Bloch's "Five Degrees..." would really be helpful here!

Thanks.

Al,
(e-mail address removed)
 
A

Al Koch

Hi Chris,
Just to clarify:
When he said UnsafeClass.class, he meant UnsafeClass.class, not
"UnsafeClass.class".

As in:

synchronized(UnsafeClass.class) {
UnsafeClass.UnsafeAPI();
}

This is actually a legal expression. It returns an object of type
java.lang.Class representing UnsafeClass. THIS object is what
synchronized static methods implicitly synchronize on. There is only one
such object for each class per classloader.

Also, I would suggest not synchronizing on strings because it's too easy
to make a typo and the compiler won't catch it for you.

You are right. I had meant
UnsafeClass.class
not a quoted string. I had been using quoted strings to reference "logical"
objects described by the string and got carried away. Thanks for keeping
the readers on the right path!

Al,
(e-mail address removed)
 
A

Al Koch

Hi Eric,
As mentioned above, I don't speculate for Sun. I *do* think
you're worrying far too much; the existence and success of big
bundles of multi-threaded Java applications suggests that the
problems are not as severe as you seem to believe. Are you, by
any chance, old enough to remember Skylab helmets?

Well, would you believe that I never looked at your email address (duh) so
when I asked if you couild speculate on why Sun wasn't (as far as I can
tell) saying much to try and clarify things it wasn't because I knew you
worked there; I thought I was just asking someone who appeared to be
credible!

After about a week of throught and research (a big part of it informed by
your posts) I now have a much better understanding of the issues. It looks
like there's a reasoanable soultion to the various issues I've raised except
for use of a J2SE/EE method that manipulates Class data or some "external
resource". I'm sure it's been obvious to you all along but the fog is now
clearing and I see that this is the area of potential vulnerability. Since
we are talking about a J2SE/EE method I have no control over who else might
be using it (in the same JVM) and how they use it so "all bets are off".
But your final comments about being overly concerned are perhaps the most
useful of all. As I said when I started the thread I'm new to threading for
Java so I did not yet have any calibration for the size of the problem. You
have been a big help in my development of the proper sense of concern here.
I'll go with your suggestion that "the sky ain't falling!". (However, it's
too bad that in a few more years we'll have to go get some "Hubble
helmets"!)

Thanks for all your help. It has been a pleasure communicating with you!

Al,
(e-mail address removed)
 
A

Al Koch

Hi John,

Thanks for your reply.

John Currier said:
The vast majority of "not thread safe" code is thread safe at the class
level (i.e., it doesn't contain "unprotected" static members) but not
at the instance level.

Take SimpleDateFormat as an example. A single instance of
,,,

The J2SE/EE docs say something about SimpleDateFormat;s synchronization.
One of the problems I'm having is the many (maybe most?) classes in the
J2SE/EE docs don't appear to say anything one way or another. In general
then, how do you deternine the degree of thread safety a class's method's
have?

Al,
(e-mail address removed)
 
J

John Currier

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.

John
http://schemaspy.sourceforge.net
 
D

Dale King

Al said:
Hello,

I am writing a Java servlet and am new to coding for thread synchronization.
I suspect that there must be an "obvious" solution to the following problem
but after sevearl days of research I can't find it!

It is my understanding that, in general, the J2SE 1.4 API is *not*
thread-safe. There are some APIs where the Sun documentation states that a
Class's methods are thread-safe (such as StringBuffer) but in general, most
of the text and web search references I have found have stated that the API
in general is not thread-safe. That means that there must be at least one
(and it's probably most) API that is not thread-safe and let me just call
such an unsafe method "UnsafeAPI()". My question is, how do I use
UnsafeAPI() and write code to make my code thread-safe?

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.
 
D

Dale King

Eric said:
`new' itself is safe for the same reason `+' is safe:
it's just an operator; it has no internal state of its own
that needs protection.

It's possible to write an unsafe constructor, but that's
a somewhat different matter. If a constructor is unsafe there's
really not much you can do about it; constructors are a lot like
static methods in this regard. However, I can think of only two
ways a constructor can be unsafe (perhaps the experts will chime
in with more):

- While building the new object, the constructor could
manipulate some other object that could be accessible
to another thread. For example, a constructor that
maintained a "registry" of constructed instances might
manipulate the registry without synchronizing. I'd
consider this a bug in the constructor.

- The constructor could put a reference to the new object
someplace where another thread could find it, and then
proceed to manipulate the new object without synchronizing.
Again, I'd consider this a constructor bug.

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
 

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,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top