Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2005

Tip: Looking for answers? Try searching our database.

Synchronized methods - correct understanding?

Thread view: 
Ian Pilcher - 14 Nov 2005 16:59 GMT
I would just like to confirm that my understanding of synchronized
methods is correct.  I believe that the two code snippets below are
equivalent.

   class C1
   {
       private int value;

       public synchronized void setValue(int newValue)
       {
           value = newValue;
       }
   }

   class C2
   {
       private int value;

       public void setValue(int newValue)
       {
           synchronized (this)
           {
               value = newValue;
           }
       }
   }

Am I correct?

Thanks!

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

mrandywarner@gmail.com - 14 Nov 2005 17:10 GMT
To an extent, yes.  Marking a method as synchronized will ensure that
no two threads enter the method at the same time (C1).  By
synchronizing on the object, you create another possible relationship
that could be good or bad depending on the desired behavior, if you
have other methods that you do not want to access during the update,
such as a getter, you can synchronize it by using the same object for
the synchronization.  But I would prefer to synchronize on the actual
value that is the purpose for the synchronization.  It is both simpler
to read, and limits the possibility of unnecessary, and possibly
dangerous sync relationships.

class C2 {
   private Integer value;
   ...
   public int getValue() {
       synchronize(value) {
           return value.intValue();
       }
   }
}
Thomas Hawtin - 14 Nov 2005 18:19 GMT
> class C2 {
>     private Integer value;
[quoted text clipped - 5 lines]
>     }
> }

IIRC, Bitter Java takes that approach in one of its code examples.

There is, however, one slight problem. The technique blatantly doesn't work.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Thomas G. Marshall - 14 Nov 2005 18:33 GMT
Thomas Hawtin coughed up:

>> class C2 {
>>     private Integer value;
[quoted text clipped - 12 lines]
>
> Tom Hawtin

:)

Signature

"So I just, uh... I just cut them up like regular chickens?"
"Sure, just cut them up like regular chickens."

Roedy Green - 14 Nov 2005 20:10 GMT
On Mon, 14 Nov 2005 18:19:17 +0000, Thomas Hawtin
<usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
who said :

>> class C2 {
>>     private Integer value;
[quoted text clipped - 9 lines]
>
>There is, however, one slight problem. The technique blatantly doesn't work.

Could you please verify the failure mechanism. I gather it is that if
someone changes "value", the lock is on the old object so it does
nothing to protect.  You can only lock on references you don't change.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Thomas G. Marshall - 14 Nov 2005 22:29 GMT
Roedy Green coughed up:
> On Mon, 14 Nov 2005 18:19:17 +0000, Thomas Hawtin
> <usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
[quoted text clipped - 18 lines]
> someone changes "value", the lock is on the old object so it does
> nothing to protect.

1. That!!!

2. It doesn't allow for outside party's to have access to the lock, which
they will need for compound operations.  His example is a disaster all
around.

...[rip]...

Signature

Forgetthesong,I'dratherhavethefrontallobotomy...

Thomas Hawtin - 15 Nov 2005 07:03 GMT
> Roedy Green coughed up:
>
[quoted text clipped - 23 lines]
>
> 1. That!!!

Yup. synchronize locks on the object, not the variable. So after you set
the value you have now switched to a different lock. Or at least
partially switched. You would need a second lock to perform the switch
thread-safely.

Something similar does work. If you had a final reference to a map or
collection, you could update the contents with a lock on the object. As
Vector/HashTable/Collections.synchronizedXxx. As an obscure point,
technically before 1.4 you would need to distribute the object holding
the reference among threads in a thread-safe manner. From 1.5, final
makes everything alright.

In a sense, it is safe to update the reference within the synchronize
block. The reference is copied and it is always the same object locked
and unlocked. However, I can't think of a use for it off the top of my
head (although I seem to remember a situation where I could have done it).

> 2. It doesn't allow for outside party's to have access to the lock, which
> they will need for compound operations.  His example is a disaster all
> around.

I have never managed to come to a decision on this. It does expose
significant implementation. For instance, it doesn't work so well with
decorators.

Writers have separate locks. This appears to have caused confusion to an
author of java.sql.DriverManager where a print and a flush are
synchronised together. Not that it particularly matters whether this
particular sequence is atomic or not.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Roedy Green - 15 Nov 2005 07:13 GMT
On Tue, 15 Nov 2005 07:03:41 +0000, Thomas Hawtin
<usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
who said :

>As an obscure point,
>technically before 1.4 you would need to distribute the object holding
>the reference among threads in a thread-safe manner. From 1.5, final
>makes everything alright.

Where did you learn about this?  could you explain in code what you
mean by "distributing the object"?
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Thomas Hawtin - 15 Nov 2005 09:14 GMT
> On Tue, 15 Nov 2005 07:03:41 +0000, Thomas Hawtin
> <usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
[quoted text clipped - 7 lines]
> Where did you learn about this?  could you explain in code what you
> mean by "distributing the object"?

Initially from the Java Memory Model list. Final field semantics are
specified in section 17.5 of JLS3, although I can't give you a reference
to a good tutorial on the subject.

By "distributing the object" [reference] I mean how a reference to an
object is copied from one thread to another. For instance, you might
write the reference in a static field, then have another thread poll it.
Without synchronisation, the reading thread may see a partially
initialised object[1]. From 1.5 final instance fields are freezed at the
end of the constructor, allowing thread-safety by immutability.

In practice witting a thread-safe-by-immutability object is just doing
the obvious. Actually exploiting those properties is more difficult. As
was compromising security by the original flawed memory model. Witting
classes with correct finalisation is just silly difficult.

Tom Hawtin

[1] Assuming the static field is non-volatile and written from outside
of class initialisation and the constructor,
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Thomas G. Marshall - 15 Nov 2005 15:22 GMT
Thomas Hawtin coughed up:
>> On Tue, 15 Nov 2005 07:03:41 +0000, Thomas Hawtin
>> <usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
[quoted text clipped - 18 lines]
> initialised object[1]. From 1.5 final instance fields are freezed at
> the end of the constructor, allowing thread-safety by immutability.

It would have been interesting to have the writing and reading of even /non/
static variables be synchronized in nature.  It would limit your ability to
code unsafely, which is sometimes needed.  However even in the 1.5 final
field case, I would still strongly suggest this not be relied upon, even in
reading only.  Use synchronized accessors/mutators.  The reason for this is
that there might be a point in the future where an engineer might be
convinced that the variable need not be final (for some reason), and there
goes your read protection.  The problem with threading corruption is that
often your code will run for 6 hours straight and /then/ die.  It's just
always worth having the *explicit* protection.

> In practice witting a thread-safe-by-immutability object is just doing
> the obvious. Actually exploiting those properties is more difficult.
[quoted text clipped - 5 lines]
> [1] Assuming the static field is non-volatile and written from outside
> of class initialisation and the constructor,
Thomas G. Marshall - 15 Nov 2005 21:11 GMT
Thomas Hawtin coughed up:

>> 2. It doesn't allow for outside party's to have access to the lock,
>> which they will need for compound operations.  His example is a
[quoted text clipped - 3 lines]
> significant implementation. For instance, it doesn't work so well with
> decorators.

The exposing of implementation to me seems more an extension of the
interface in a way.  It is, for example, far more innocuous than allowing
direct access to a member variable, to pick one thing out of a hat.

One way or another, if an object is to be thread safe and allow compound
operations, /something/ has to be done.  If you want it to fold protection
entirely within the object *and* allow arbitrary compound operations, it
*is* possible to implement something that I am not 100% comfortable with:

       public void runSafely(Runnable runnable)
       {
           synchronized (internalLock) { runnable.run(); }
       }

or something similar to keep the internalLock nonpublished.  Otherwise you
need to have the lock externally settable/releasable.

Synchronized arraylists, for example, require you to use themselves as the
lock, if you're going to protect against all access to it from anywhere not
under your control.  At first I cringed at the idea, but have since grown
entirely comfortable with it.
Thomas G. Marshall - 14 Nov 2005 18:32 GMT
mrandywarner@gmail.com coughed up:
> To an extent, yes.  Marking a method as synchronized will ensure that
> no two threads enter the method at the same time (C1).  By
[quoted text clipped - 9 lines]
> class C2 {
>    private Integer value;

You need an actual instance here

   value = new Integer(0);

>    ...
>    public int getValue() {
[quoted text clipped - 3 lines]
>    }
> }

This is not a good idea in general as it goofs up compound operations later.
For example, the following:

   C2 c = new C2();

   c.setValue(c.getValue() + 1);

is not going to work and is going to need external synchronization one way
or the other.  Using your technique, their is no way to get access to the
lock.  It is far better to have the instance itself hold the lock, to allow
this:

   synchronized(c)
   {
       c.setValue(c.getValue() + 1);
   }

If you did it your way, but made the embedded Integer "value" object
exposed:

   public class C2
   {
       // (.....code...)
       public Object getLock() {return value;}
   }

Then you could use it this way:

   synchronized(c.getLock())
   {
       c.setValue(c.getValue() + 1);
   }

But this is fraught with peril, because it is *not* what is expected by most
engineers.

This is to the side of whether or not you should use the

   <scope> synchronized <type> <method name> {<body>}

or

   <scope> <type> <method name> { synchronized(this) {<body>} }

I strongly suggest the latter unless you *absolutely* know that no
additional code will ever be added to the method that does not need
synchronization, and that you won't need the speed differential.

Signature

"So I just, uh... I just cut them up like regular chickens?"
"Sure, just cut them up like regular chickens."

Thomas G. Marshall - 14 Nov 2005 22:23 GMT
Thomas G. Marshall coughed up:

...[rip]...

> If you did it your way, but made the embedded Integer "value" object
> exposed:
[quoted text clipped - 4 lines]
>        public Object getLock() {return value;}
>    }

Holy crap no!

It dawned on me on my way to a meeting.  I've been chomping at the bit to
write this partial retraction.  I forgot that the Integer classes are
immutable!  This would (of course) mean he would only be creating a new one
for every value, and hence such a lock mechanism would be lost every time.

So there is yet /another/ reason to not do it that way.  My other examples
stand as is.

Signature

Forgetthesong,I'dratherhavethefrontallobotomy...

Thomas Fritsch - 14 Nov 2005 17:40 GMT
> I would just like to confirm that my understanding of synchronized
> methods is correct.  I believe that the two code snippets below are
> equivalent.

>         public synchronized void setValue(int newValue)
>         {
>             value = newValue;
>         }

>         public void setValue(int newValue)
>         {
[quoted text clipped - 3 lines]
>             }
>         }

> Am I correct?
Yes. Declaring a non-static method as synchronized is exactly equivalent
to wrapping the whole method body with 'synchronized(this) { ... }'.

The Language Spec elaborates more about that:
http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#30531
Signature

"Thomas:Fritsch$ops:de".replace(':','.').replace('$','@')

Ian Pilcher - 14 Nov 2005 17:59 GMT
> Yes. Declaring a non-static method as synchronized is exactly equivalent
> to wrapping the whole method body with 'synchronized(this) { ... }'.

Thanks!

Not sure why I find the second version easier to understand.  Too much
time spend with pthreads, I suppose.

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Chris Uppal - 14 Nov 2005 17:53 GMT
> Am I correct?

You are correct.

   -- chris
Roedy Green - 14 Nov 2005 17:58 GMT
On Mon, 14 Nov 2005 10:59:04 -0600, Ian Pilcher
<i.pilcher@comcast.net> wrote, quoted or indirectly quoted someone who
said :

>Am I correct?

I think you are.

You can see if there are any differences at all by decompilng both
with Javap.

See http://mindprod.com/jgloss/disassembler.html
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

abrasivesponge@gmail.com - 14 Nov 2005 18:12 GMT
> I would just like to confirm that my understanding of synchronized
> methods is correct.  I believe that the two code snippets below are
[quoted text clipped - 26 lines]
>
> Thanks!

Just so you know...It would be better now to scrap the synchronized
keyword for thread management and use the new concurrency locks in Java
1.5 (if you are using that version)
The reason being you have a wider range of new mechanisms for you lock
in that package.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.