Synchronized access

S

Stanimir Stamenkov

I've read statements that using a separate object to lock on, rather
than using a synchronized method, to synchronize an operation on
other object is better, i.e.:

public class Pencho {

private int mField;

private Object mLock = new Object();

public int makeSomething(int pNumber) {
syncrhonized (mLock) {
mFiled = (mField + pMagicNumber) / 2;
return mField;
}
}
}

and:

public class Pencho {

private int mField;

public synchronized int makeSomething(int pNumber) {
mFiled = (mField + pMagicNumber) / 2;
return mField;
}
}

Is there benefit of using the first approach over the second one
(and specifically for the above simple example)?
 
P

Paul Bilnoski

I've read statements that using a separate object to lock on, rather
than using a synchronized method, to synchronize an operation on
other object is better, i.e.:

public class Pencho {

private int mField;

private Object mLock = new Object();

public int makeSomething(int pNumber) {
syncrhonized (mLock) {
mFiled = (mField + pMagicNumber) / 2;
return mField;
}
}
}

and:

public class Pencho {

private int mField;

public synchronized int makeSomething(int pNumber) {
mFiled = (mField + pMagicNumber) / 2;
return mField;
}
}

Is there benefit of using the first approach over the second one
(and specifically for the above simple example)?
I believe there isn't a difference between placing all the code in the
method within an extra 'synchronized (this)' block. The synchronized block
lets you localize the critical section of code. If the entire method is the
critical section, then it's a (slight) convenience to just tag the entire
method with a mutex.

--Paul
 
T

Tony Morris

Paul Bilnoski said:
I believe there isn't a difference between placing all the code in the
method within an extra 'synchronized (this)' block. The synchronized block
lets you localize the critical section of code. If the entire method is the
critical section, then it's a (slight) convenience to just tag the entire
method with a mutex.

--Paul

There is a HUGE difference between the two posted examples.
One might argue that:
synchronized void m(){}
is equivalent to
void m(){synchronized(this){}}
however, this is not entirely correct - and there is a significant
performance benefit gained from taking the former approach.

Is is extremely important to recognise that the two posted examples do not
make this comparison - the lock (aka monitor) is not a reference to 'this',
which causes a VERY BIG functional difference - a difference which I won't
explain in details since it is already well covered elsewhere.

"to synchronize an operation on other object is better, i.e.:"
I assume you mean "to synchronize an operation on an object that is not
'this' is better", in which case, this is entirely incorrect and quite
often, the contrary is true (that synchronizing on anything but 'this' is
bad practice).
There is a benefit gained by synching on an internal object, however, as
this is improving encapsulation i.e. you aren't exposing your object monitor
(i.e. all other references that are == to 'this').
If you don't understand some of these fundamental practices, I would suggest
you follow the less problematic (loosely speaking) approach of synchronizing
only on a 'this' reference.

For further information:
http://java.sun.com/docs/books/tutorial/essential/threads/index.html
"Taming Java Threads", Allen Holub

Note: Usually I wouldn't give such a detailed explanation, but I can't
resist when I see blatant false advice being handed out.

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
S

Stanimir Stamenkov

/Tony Morris/:
"to synchronize an operation on other object is better, i.e.:"
I assume you mean "to synchronize an operation on an object that is not
'this' is better", in which case, this is entirely incorrect and quite
often, the contrary is true (that synchronizing on anything but 'this' is
bad practice).
There is a benefit gained by synching on an internal object, however, as
this is improving encapsulation i.e. you aren't exposing your object monitor
(i.e. all other references that are == to 'this').
If you don't understand some of these fundamental practices, I would suggest
you follow the less problematic (loosely speaking) approach of synchronizing
only on a 'this' reference.

I understand my example uses two different approaches to synchronize
operation on a 'Pencho' type of object (it modifies some of its
member fields). While in the first case the operation locks on an
internal object (other than 'this Pencho') the second locks on 'this
Pencho' itself.

I think my question was clear enough, but I was more interested if
there's any benefit in the performance. If your answer is: "There is
a benefit gained by synching on an internal object, however, as this
is improving encapsulation i.e. you aren't exposing your object
monitor (i.e. all other references that are == to 'this')." - o.k.,
but your other writings just confuse me.
Note: Usually I wouldn't give such a detailed explanation, but I can't
resist when I see blatant false advice being handed out.

Thank you for the effort.

Best Regards,
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Tony said:
There is a HUGE difference between the two posted examples.
One might argue that:
synchronized void m(){}
is equivalent to
void m(){synchronized(this){}}
however, this is not entirely correct - and there is a significant
performance benefit gained from taking the former approach.

Tony is correct here, although by reading the java language
specification you might think otherwise. The relevant info can be found
in the JVM spec. Basically:

synchronized void m() {}

sets a flag for method m in the method table saying that the method is
synchronized. Handling the locks/unlocks is left to the VM.

void m() { synchronized(this) {}}

however, results in the compiler generating monitorenter/monitorexit
instructions in the method body. This includes an exception handler with
monitorexit at the end of the method, since locks must be released no
matter what happens.

So prefer the method synchronization over synchronized(this) since it
makes the code smaller, and the VM probably has some special tricks for
the former. Not that I'd expect this to make any significant difference
in practice.
Is is extremely important to recognise that the two posted examples do not
make this comparison - the lock (aka monitor) is not a reference to 'this',
which causes a VERY BIG functional difference - a difference which I won't
explain in details since it is already well covered elsewhere.

"to synchronize an operation on other object is better, i.e.:"
I assume you mean "to synchronize an operation on an object that is not
'this' is better", in which case, this is entirely incorrect and quite
often, the contrary is true (that synchronizing on anything but 'this' is
bad practice).

I agree.
 

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,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top