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 / June 2006

Tip: Looking for answers? Try searching our database.

synchronized block in synchronized static method

Thread view: 
dmcreyno - 26 Jun 2006 17:59 GMT
I recently stumbled across this idiom.

 public static synchronized int getThreadCountMax()
 {
   synchronized (ARTClientThread.class)
   {
     return threadCountMax;
   }
 }

Its a synchronized static method with a synchronized block. Looks
redundant to me. Doesn't the synchronized static method use the class
object?
Thomas Fritsch - 26 Jun 2006 18:14 GMT
> I recently stumbled across this idiom.
>
[quoted text clipped - 8 lines]
> Its a synchronized static method with a synchronized block. Looks
> redundant to me.
It is just as dumb as writing this:
  public static int getThreadCountMax()
  {
    synchronized (ARTClientThread.class)
    {
      synchronized (ARTClientThread.class)
      {
        return threadCountMax;
      }
    }
  }

> Doesn't the synchronized static method use the class
> object?
I does.

Signature

Thomas

Robert Klemme - 26 Jun 2006 18:29 GMT
> I recently stumbled across this idiom.
>
[quoted text clipped - 9 lines]
> redundant to me. Doesn't the synchronized static method use the class
> object?

It does - but it's own class.  If this code is not in class
ARTClientThread then it has different semantics than the version without
the block.

Kind regards

    robert
Chris Uppal - 26 Jun 2006 18:39 GMT
>   public static synchronized int getThreadCountMax()
>   {
[quoted text clipped - 7 lines]
> redundant to me. Doesn't the synchronized static method use the class
> object?

If getThreadCountMax() is a method at the outer level of ARTClientThread then
it is redundant.

If it's a member of any other class (including classes nested inside
ARTClientThread) then it's not redundant.   In that case, depending on the
design of the locking strategy, it could be any of: wasteful, absolutely
necessary, or an invitation to create deadlocks.

   -- chris
Eric Sosman - 26 Jun 2006 18:51 GMT
dmcreyno wrote On 06/26/06 12:59,:
> I recently stumbled across this idiom.
>
[quoted text clipped - 9 lines]
> redundant to me. Doesn't the synchronized static method use the class
> object?

   If the method is part of the ARTClientThread class, the
same Class object is locked redundantly.

   If the method is part of some other class, that class'
Class object and ARTClientThread.class are distinct and both
are locked once each.  This isn't "redundant," but it seems
"useless."

   Has this code been victimiz-- er, "improved" by one of
those semi-automatic refactoring tools?  The gadgets that
take the thought out of coding and produce thoughtless code?

Signature

Eric.Sosman@sun.com

dmcreyno - 26 Jun 2006 18:54 GMT
As others have asked, it is a method on ARTClientThread. So, redundant
it is.
> I recently stumbled across this idiom.
>
[quoted text clipped - 9 lines]
> redundant to me. Doesn't the synchronized static method use the class
> object?
Mark Space - 27 Jun 2006 00:30 GMT
> As others have asked, it is a method on ARTClientThread. So, redundant
> it is.

That's wild.  Does Java sychronized keyword have code to check "don't
lock this if I have already locked this?"  'Cause otherwise it's an
instant deadlock...

>> I recently stumbled across this idiom.
>>
[quoted text clipped - 9 lines]
>> redundant to me. Doesn't the synchronized static method use the class
>> object?
Chris Smith - 27 Jun 2006 00:49 GMT
> > As others have asked, it is a method on ARTClientThread. So, redundant
> > it is.
>
> That's wild.  Does Java sychronized keyword have code to check "don't
> lock this if I have already locked this?"  'Cause otherwise it's an
> instant deadlock...

Locks are recursive in Java; hence, no deadlock.

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Mark Space - 27 Jun 2006 18:23 GMT
>>> As others have asked, it is a method on ARTClientThread. So, redundant
>>> it is.
[quoted text clipped - 3 lines]
>
> Locks are recursive in Java; hence, no deadlock.

I don't see how recursion would help, but I'll take your word on the no
deadlock bit.

Do you mean "able to be used in recursive algorithms" maybe?  I think
that might be re-entrant or something.
Chris Smith - 27 Jun 2006 18:52 GMT
> > Locks are recursive in Java; hence, no deadlock.
>
[quoted text clipped - 3 lines]
> Do you mean "able to be used in recursive algorithms" maybe?  I think
> that might be re-entrant or something.

A recursive lock is a lock that keeps track of who is holding it, and a
lock count.  When the holder tries to grab the lock a second time, it
simply increments that counter.  When the holder releases the lock,
then, it decrements that counter.  Only when the counter reaches zero is
the lock actually released.

This does solve this specific deadlock problem.  Of course, it's still
possible to write deadlocks in Java, but it does require two locks.

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Mark Space - 27 Jun 2006 20:43 GMT
>>> Locks are recursive in Java; hence, no deadlock.
>>>
[quoted text clipped - 9 lines]
> then, it decrements that counter.  Only when the counter reaches zero is
> the lock actually released.

Ok, first time I've heard that term, applied to mutex or semaphores
anyway.  Thanks!
Red Orchid - 26 Jun 2006 22:48 GMT
"dmcreyno" <david.mcreynolds@gmail.com> wrote or quoted in
Message-ID: <1151341182.628313.267040@i40g2000cwc.googlegroups.com>:

>   public static synchronized int getThreadCountMax()
>   {
[quoted text clipped - 7 lines]
> redundant to me. Doesn't the synchronized static method use the class
> object?

From a different standpoint ..

In the above example,  'threadCountMax' seems to be 'int' variable.
As I know as, the operation that reads/writes 'int' variable is atomic.
Therefore, 'synchronized' will not be required.
Mike Schilling - 27 Jun 2006 01:43 GMT
> "dmcreyno" <david.mcreynolds@gmail.com> wrote or quoted in
> Message-ID: <1151341182.628313.267040@i40g2000cwc.googlegroups.com>:
[quoted text clipped - 16 lines]
> As I know as, the operation that reads/writes 'int' variable is atomic.
> Therefore, 'synchronized' will not be required.

If there's another method, say

   public static synchronized int incrementThreadCount()
   {
       threadCountMax++;
   }

Both synchronized blocks are required to ensure that changes to the value
made in one thread are seen in another.
Red Orchid - 27 Jun 2006 04:09 GMT
"Mike Schilling" <mscottschilling@hotmail.com> wrote or quoted in
Message-ID: <%a%ng.123621$dW3.96134@newssvr21.news.prodigy.com>:

> If there's another method, say
>
[quoted text clipped - 5 lines]
> Both synchronized blocks are required to ensure that changes to the value
> made in one thread are seen in another.

I want that you go into details about why both synchronized blocks
are required.

My point is:

First, let's consider 'case_a'.

<case_a>
class Thread_1 .... {
   int getValue() {
       return some_Int_Var; //  <- #1
   }
}

class Thread_2 .... {
   void setValue() {
       ...
       some_Int_Var = ....; // <- #2
       ...
   }
}

Thread_1 can not intercept the operation #2 while #2 writes some
value on 'some_Int_Var'.

Thread_2 can not intercept the operation #1 while #1 is working
because #1 is atomic.  And #1 do not produce any effect on #2
because #1 is only reading of 'some_Int_Var'.
</case_a>

Next,

<case_b>
class Thread_3 .... {
   void setValue() {
       ...
       some_Int_Var = ... + some_Int_Var; // <- #3
       ...
   }
}

class Thread_4 .... {
   void setValue() {
       ...
       some_Int_Var = ... + some_Int_Var; // <- #4
       ...
   }
}

Both #3 and #4 are not atomic operations.   That is,
Thread_4 can intercept the operation #3 while #3 is working.
In ths case,  both synchronized blocks are required.
</case_b>

Last,

<case_c>
class Thread_5 .... {
   int getValue() {
       return some_Int_Var; //  <- #5
   }
}

class Thread_6 .... {
   void setValue() {
       ...
       some_Int_Var = ... + some_Int_Var; // <- #6
       ...
   }
}

class Thread_7 .... {
   void setValue() {
       ...
       some_Int_Var = ... + some_Int_Var; // <- #7
       ...
   }
}

#5 do not need 'synchronized block'.  But,
both #6 and #7 need synchronized blocks.
</case_c>

Original poster's example is the case of #1 or #5.
Therefore,
synchronized block will not be required with the example.
Chris Smith - 27 Jun 2006 04:34 GMT
> I want that you go into details about why both synchronized blocks
> are required.

The concurrency model of Java is specified very loosely.  There are
certain pairs of operations that may occur in which it may be inferred
that one operation happened before the other.  For example, if two
operations happen in the same thread, then it may be inferred that there
is an order to the operations (the same order in which they appear in
the code).  Also, if threads get and release a monitor via synchronized
blocks, then this allows you to validly conclude that one thread
released the synchronized block before the other thread got it.  There
are a few more.  These pairs of operations are listed in the language
specification.  Outside of these pairs of operations, though, the
implementation is free to act as if operations happened in any order
whatsoever, regardless of what the order actually is.  The result is
that if threads never do certain things, then the implementation may act
as if one thread hasn't yet done the stuff that it's done, from the
perspective of the other thread.

So that's the formal reason.  However, there is another question.  Why
is it specified that way?  It's specified that way to give flexibility
to the implementation.  Implementations have to deal with complexity
that you couldn't dream of sometimes.  Many CPUs will feel free to
change the order in which they execute various instructions of your
code, unless they are explicitly told not to... and telling them not to
may result in severe performance costs due to pipeline stalls.  The JVM
might even be running on a distributed network, where it's very
expensive to go check if some other thread has modified an object, and
you'd rather put it off until you absolutely need to do so.  Not to
mention that future technologies will have even greater challenges.  I
actually see it as quite likely that future multiprocessing CPU
architectures will be more like distributed applications, in which it's
more expensive to access memory that's "close" to the CPU than memory
that's far away.  That leads to more scalable designs, if you can figure
out the compilation challenges of managing how to put things closer to
their respective CPUs in memory.  The JVM concurrency model is written
as loosely as possible to let you write correct code by applying
synchronization primitives, but otherwise give the implementation as
much flexibility as possible in handling these kinds of issues.

So that's why.  If you don't understand, though, the rule of thumb is
still pretty simple.  Don't assume that you'll see changes made in a
different thread unless you enter a synchronized block for a montior
that was held by the other thread when the changes were made.  Don't
assume that other threads can see your changes unless you enter a
synchronized block when you make them (and the other threads grab the
same monitor before reading).

> Thread_1 can not intercept the operation #2 while #2 writes some
> value on 'some_Int_Var'.

Atomicity is a different question.  The JVM does guarantee that all
attempts to read an int will return an actual value, and not some half-
way in between thing.  However, say that thread 1 writes to an int
variable, and then thread 2 reads that same variable.  Thread two will
get *either* the value before thread 1 wrote to it, *or* the value
after, but there's no way to tell which unless there's some synchronized
block (or some other way to prove a sequence that's acceptable in the
JLS concurrency model) involved.

> Therefore,
> synchronized block will not be required with the example.

Yes, it will.  Things are more complicated than you are assuming,
because there is no global order for operations in the program.  Things
can happen in different orders depending on the observer.  Almost like
special relativity...

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Chris Uppal - 27 Jun 2006 10:51 GMT
> Therefore,
> synchronized block will not be required with the example.

[This is in addition to what Chris Smith has already explained]

Consider this:

   privant int value;

   public int getValue() { return value; }

   public void aMethod()
   {
       while (true)
           doSomethingWith(getValue());
   }

Since getValue() is not synchronised, and uses no sychronisation blocks, the
compiler (which really means JITer) is perfectly within its right to first
inline the method call, as if the original Java source was:

   public void aMethod()
   {
       while (true)
           doSomethingWith(value);
   }

and then to "notice" that value does not change during the loop, and to
optimise the field access into a local variable access:

   public void aMethod()
   {
       int __xyz123 = value;
       while (true)
           doSomethingWith(__xyz123);
   }

So, in another thread /does/ change value, the loop will never "see" the new
value.

Synchronisation acts not only to control the (potentially very loose) coupling
between the state of RAM seen by different CPUs, but also to inform the
optimiser of the limits to what it is allowed to assume.

   -- chris


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



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