Threads 101 question

M

Mike Smith

How do you handle this paradox?

1. Object myObject = new Object();
2.
3. // Threads started here which
4. // may set myObject to null
5.
6. if (myObject != null) {
7. synchronized (myObject) {
8. // Ref to myObject here
9. }
10. }

How can you be sure another thread will not swoop in and set myObject
to null in between lines 6 and 7 before you have a chance to get a
lock on it? You cannot synchronize on myObject if it is set to null
without throwing an exception. Do you just move the synchronized
block to before the IF statement and catch the exception if myObject
is null or is there a more elegant approach?

Mike
 
E

Eric Sosman

Mike said:
How do you handle this paradox?

1. Object myObject = new Object();
2.
3. // Threads started here which
4. // may set myObject to null
5.
6. if (myObject != null) {
7. synchronized (myObject) {
8. // Ref to myObject here
9. }
10. }

How can you be sure another thread will not swoop in and set myObject
to null in between lines 6 and 7 before you have a chance to get a
lock on it? You cannot synchronize on myObject if it is set to null
without throwing an exception. Do you just move the synchronized
block to before the IF statement and catch the exception if myObject
is null or is there a more elegant approach?

Another thread can indeed swoop in and do the dirty deed.
However, `myObject' cannot be a method-local variable or method
parameter (such things are private to each thread), so the deed
can only be done if `myObject' is a member variable in some
other object (or class). And in that case, the thing you want to
lock is not the object pointed to by `myObject', but the object
containing the `myObject' member.

Or to look at it a slightly different way: The thing that
the threads are sharing is not really the newly-created Object,
but the object that contains `myObject'. Since they share that
enclosing object, they must synchronize their accesses to it.
 
L

Liz

Mike Smith said:
How do you handle this paradox?

1. Object myObject = new Object();
2.
3. // Threads started here which
4. // may set myObject to null
5.
6. if (myObject != null) {
7. synchronized (myObject) {
8. // Ref to myObject here
9. }
10. }

How can you be sure another thread will not swoop in and set myObject
to null in between lines 6 and 7 before you have a chance to get a
lock on it? You cannot synchronize on myObject if it is set to null
without throwing an exception. Do you just move the synchronized
block to before the IF statement and catch the exception if myObject
is null or is there a more elegant approach?

Mike

How about if you just an another 'if' between lines 7 and 8
 
M

Mike Smith

myObject would never be null since the synchronized operation would
have thrown an exception if it was null and would have locked it for
me if it was not null, so an IF there makes no difference. It will
never get there without myObject being a non-null reference -
guaranteed. Someone please correct me if I'm wrong.

I think the earlier post from Eric Sosman nails it but I'm still
digesting that information.

Mike
 
M

Mike Smith

Interesting... So to lock a critical block within a method I would use
synchronize(this) as follows:

1. myObject = new Object(); // myObject is now a class var
2.
3. // Threads started here which
4. // may set myObject to null
5. if (xxx) {
6. // non critical code goes here
7. } else {
8. synchronize(this) {
9. if (myObject != null) {
10. // critcal code goes here
11. }
12. }
13.}

Thanks for your help, assuming I got it right. (synchronize this, wasn't
that a Billy Crystal movie?)

Mike
 
S

Steve Horsley

Mike said:
How do you handle this paradox?

1. Object myObject = new Object();
2.
3. // Threads started here which
4. // may set myObject to null
5.
6. if (myObject != null) {
7. synchronized (myObject) {
8. // Ref to myObject here
9. }
10. }

How can you be sure another thread will not swoop in and set myObject
to null in between lines 6 and 7 before you have a chance to get a
lock on it? You cannot synchronize on myObject if it is set to null
without throwing an exception. Do you just move the synchronized
block to before the IF statement and catch the exception if myObject
is null or is there a more elegant approach?

Mike

In the code you posted, another thread cannot accedd myObject because it
is a thread-local variable, not a class or instance variable.

Assuming that myObject was (say) an instance variable of an object, then
I suggest you should only take one bite at the cherry, like this:

// get the (possibly null) reference to the lock object
Object myObject = holderObject.getLockObject();

// now no-one can take it from us because we have a
// thread-local reference to it.
if(myObject != null) {
// do something...


Maybe you should be synchronizing on the next-level-up object
that holds the lock object instead - sync on the parent not the child?

Steve
 
E

Eric Sosman

Mike said:
Interesting... So to lock a critical block within a method I would use
synchronize(this) as follows:

1. = new Object(); // myObject is now a class var
2.
3. // Threads started here which
4. // may set myObject to null
5. if (xxx) {
6. // non critical code goes here
7. } else {
8. synchronize(this) {
9. if (myObject != null) {
10. // critcal code goes here
11. }
12. }
13.}

Thanks for your help, assuming I got it right. (synchronize this, wasn't
that a Billy Crystal movie?)

Even though `synchronize' marks a region of code where
a lock is to be held, I think it's easier to forget about
the code and concentrate on the data. That is, instead of
thinking about which pieces of code execute with a lock, think
about which data objects require protection against simultaneous
access.

In your case, `myObject' is a member of some other object,
the `this' above. `myObject' happens to be a reference variable,
but it could just as well be a `double' or an `int': whatever
it is, it's part of the "value" of the `this' object. If two
or more threads are going to race each other to muck with the
value of `this', their accesses to `this' must be protected.
(There are some exceptions: Certain operations on some primitive
types are guaranteed to be "atomic," and read-only accesses need
not be protected against each other. Except for such special
cases, though, the rule holds: Each shared object can only be
modified or inspected while its lock is held.)

Your revised code is now safe *provided* the other threads
also synchronize on `this' (that is, on a reference to the same
"ur-object;" it won't be called `this' in those threads) when
they're mucking about with the `myObject' member. Your line 8
will not provide protection all by itself; the rest of the code
must follow the same discipline.

So: Not only must Billy Crystal `synchronize(this)', but
Robert De Niro must also `synchronize(that)'.
 
M

Mike Smith

I got it! I will thead-way safely now.

I think it was a movie about Java called "Synchronize This" where
Billy Crystal played Scott McNeeley and Robert De Niro played Bill
Gates and - oh wait, that wasn't a movie, it really happened! ;-)

Mike


----- Original Message -----
From: "Eric Sosman" <[email protected]>
Newsgroups: comp.lang.java.programmer
Sent: Wednesday, May 12, 2004 1:31 PM
Subject: Re: Threads 101 question
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top