Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > How do I use the Java API in a Thread-Safe Manner?

Reply
Thread Tools

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

 
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      06-23-2005
In article <(E-Mail Removed)>,
Al Koch <(E-Mail Removed)> wrote:
>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/developerwork...-threads1.html

http://www-106.ibm.com/developerwork...-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 ....

--
| B. L. Massingill
| ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
 
 
 
Chris Head
Guest
Posts: n/a
 
      06-23-2005
-----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-----
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      06-23-2005


Al Koch wrote:
> [...] 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?

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
Al Koch
Guest
Posts: n/a
 
      06-23-2005
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/developerwork...-threads1.html
>
> http://www-106.ibm.com/developerwork...-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 Removed)


 
Reply With Quote
 
Al Koch
Guest
Posts: n/a
 
      06-23-2005
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 Removed)


 
Reply With Quote
 
Al Koch
Guest
Posts: n/a
 
      06-23-2005
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 Removed)


 
Reply With Quote
 
Al Koch
Guest
Posts: n/a
 
      06-23-2005
Hi John,

Thanks for your reply.

"John Currier" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
> 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 Removed)


 
Reply With Quote
 
John Currier
Guest
Posts: n/a
 
      06-23-2005
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

 
Reply With Quote
 
Dale King
Guest
Posts: n/a
 
      06-24-2005
Al Koch wrote:
> 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.
--
Dale King
 
Reply With Quote
 
Dale King
Guest
Posts: n/a
 
      06-24-2005
Eric Sosman wrote:
>
> `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/mem...edLocking.html

--
Dale King
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
platform specific API or C standard API George2 C Programming 13 11-13-2007 06:29 PM
.Net Profiler API in 64 bit windows -FunctionMapper callback API =?Utf-8?B?TGVv?= Windows 64bit 0 09-05-2007 06:10 PM
Profiling API or Membership API John123 ASP .Net 0 10-20-2006 03:18 PM
Calling the C API from Python and Python program from same C API -bidirectional Praveen, Tayal (IE10) Python 0 03-17-2005 06:33 AM
What API replaces the unlock API that existed in gcc 2.9.3? Shlomo Anglister C++ 1 08-02-2004 06:50 PM



Advertisments