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?

 
 
Al Koch
Guest
Posts: n/a
 
      06-22-2005
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

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


 
Reply With Quote
 
 
 
 
Chris Head
Guest
Posts: n/a
 
      06-22-2005
-----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 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+gxSrXuMbw1YRAoVhAJ9k5O12TzFUweVs0eiSFC TTltADhQCcCf3r
GFmvh7D4UjJRKByL9gscOZ4=
=ROSq
-----END PGP SIGNATURE-----
 
Reply With Quote
 
 
 
 
Al Koch
Guest
Posts: n/a
 
      06-22-2005
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 Removed)


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-22-2005


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

--
(E-Mail Removed)

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


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-22-2005


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


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

>> 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");
> }


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

>> 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?


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

--
(E-Mail Removed)

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

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


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


> 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 Removed)



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



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

 
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