Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #30912 > unrolled thread

a simple multi-thread question

Started byJohn <xsli2@yahoo.com>
First post2015-01-26 07:40 -0800
Last post2015-01-28 21:55 +0200
Articles 10 — 6 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  a simple multi-thread question John <xsli2@yahoo.com> - 2015-01-26 07:40 -0800
    Re: a simple multi-thread question Arne Vajhøj <arne@vajhoej.dk> - 2015-01-26 10:53 -0500
    Re: a simple multi-thread question Robert Klemme <shortcutter@googlemail.com> - 2015-01-26 07:54 -0800
    Re: a simple multi-thread question Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-01-26 10:55 -0500
      Re: a simple multi-thread question Robbie Brown <rob@example.com> - 2015-01-26 18:05 +0000
        Re: a simple multi-thread question Robbie Brown <rob@example.com> - 2015-01-26 18:08 +0000
          Re: a simple multi-thread question Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-01-26 17:19 -0500
        Re: a simple multi-thread question Arne Vajhøj <arne@vajhoej.dk> - 2015-01-26 13:27 -0500
          Re: a simple multi-thread question Robbie Brown <rob@example.com> - 2015-01-26 19:51 +0000
    Re: a simple multi-thread question Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2015-01-28 21:55 +0200

#30912 — a simple multi-thread question

FromJohn <xsli2@yahoo.com>
Date2015-01-26 07:40 -0800
Subjecta simple multi-thread question
Message-ID<60c8877a-8321-4ba5-ab9a-8ccabd77874b@googlegroups.com>
Hi:

I am amazed at what I saw:

synchronized private void print()
{
     System.out.println("printing A");
     System.out.println("printing B");
     System.out.println("printing C");
}

There were two threads running. I was expecting to see:

printing A
printing B
printing C
printing A
printing B
printing C

However, I saw this:

printing A
printing A
printing B
printing C
printing B
printing C

I saw:
printing APrinting A

printing B
printing B
printing C
printing C

I thought the method is atomic. Is that because the byte stream to show up on the linux terminal is messed up in an unpredicatable way?

Thank you.

[toc] | [next] | [standalone]


#30914

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-01-26 10:53 -0500
Message-ID<54c66312$0$285$14726298@news.sunsite.dk>
In reply to#30912
On 1/26/2015 10:40 AM, John wrote:
> I am amazed at what I saw:
>
> synchronized private void print()
> {
>       System.out.println("printing A");
>       System.out.println("printing B");
>       System.out.println("printing C");
> }
>
> There were two threads running. I was expecting to see:
>
> printing A
> printing B
> printing C
> printing A
> printing B
> printing C
>
> However, I saw this:
>
> printing A
> printing A
> printing B
> printing C
> printing B
> printing C
>
> I saw:
> printing APrinting A
>
> printing B
> printing B
> printing C
> printing C
>
> I thought the method is atomic. Is that because the byte stream to show up on the linux terminal is messed up in an unpredicatable way?

It is atomic for the object instance.

Multiple threads single instance will give you what you expect.

Multiple threads with each their own instance will give you what you see.

Arne

[toc] | [prev] | [next] | [standalone]


#30915

FromRobert Klemme <shortcutter@googlemail.com>
Date2015-01-26 07:54 -0800
Message-ID<3958fd06-9f61-456a-9cee-4e8daaca9a43@googlegroups.com>
In reply to#30912
On Monday, January 26, 2015 at 4:40:51 PM UTC+1, John wrote:
> Hi:
> 
> I am amazed at what I saw:
> 
> synchronized private void print()
> {
>      System.out.println("printing A");
>      System.out.println("printing B");
>      System.out.println("printing C");
> }
> 
> There were two threads running. I was expecting to see:
> 
> printing A
> printing B
> printing C
> printing A
> printing B
> printing C
> 
> However, I saw this:
> 
> printing A
> printing A
> printing B
> printing C
> printing B
> printing C
> 
> I saw:
> printing APrinting A
> 
> printing B
> printing B
> printing C
> printing C
> 
> I thought the method is atomic. Is that because the byte stream to show up on the linux terminal is messed up in an unpredicatable way?

It's an instance method and not a class method (missing "static" keyword).  You probably created two instances, one for each thread.  But then, each gets their own mutex.  Which makes the mutexes moot.

Cheers

robert

[toc] | [prev] | [next] | [standalone]


#30916

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-01-26 10:55 -0500
Message-ID<ma5o15$s9p$1@dont-email.me>
In reply to#30912
On 1/26/2015 10:40 AM, John wrote:
>
> I am amazed at what I saw:
>
> synchronized private void print()
> {
>       System.out.println("printing A");
>       System.out.println("printing B");
>       System.out.println("printing C");
> }
> [... he gets interleaved output ...]

     Each Java object has its own lock ("monitor"), independent of the
locks belonging to other Java objects.  When you call a synchronized
instance method, Java acquires the lock of the "this" object before
proceeding, and releases it when the method finishes.  If there are
several object instances floating around, there are several "this"
and several independent locks.

> I thought the method is atomic.

     No.  Synchronization is not about methods (or code blocks), but
about objects: You lock the *object*, not a method.  If there are
four baristas at the Starcrossed shop, you "lock" only one of them
while placing your order, you do not "lock" the entire place-an-order
procedure and keep other customers from being serviced.

     Time to re-open your textbook, I think.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#30919

FromRobbie Brown <rob@example.com>
Date2015-01-26 18:05 +0000
Message-ID<ma5vk9$vu7$1@dont-email.me>
In reply to#30916
On 26/01/15 15:55, Eric Sosman wrote:
> On 1/26/2015 10:40 AM, John wrote:
>>
>> I am amazed at what I saw:
>>
>> synchronized private void print()
>> {
>>       System.out.println("printing A");
>>       System.out.println("printing B");
>>       System.out.println("printing C");
>> }
>> [... he gets interleaved output ...]
>
>      Each Java object has its own lock ("monitor"), independent of the
> locks belonging to other Java objects.  When you call a synchronized
> instance method, Java acquires the lock of the "this" object before
> proceeding, and releases it when the method finishes.  If there are
> several object instances floating around, there are several "this"
> and several independent locks.
>
>> I thought the method is atomic.
>
>      No.  Synchronization is not about methods (or code blocks), but
> about objects: You lock the *object*, not a method.

Are you sure?

If you have a class with two methods and one (or more) of them is 
synchronized and one (or more) isn't then a thread can obtain the lock 
on an instance of that class which locks out all other threads from the 
synchronized methods but the non synchronized methods of that instance 
are still available to other threads.

At least that's how I remember it.

-- 
Not floundering ... just fishing

[toc] | [prev] | [next] | [standalone]


#30920

FromRobbie Brown <rob@example.com>
Date2015-01-26 18:08 +0000
Message-ID<ma5vpo$vu7$2@dont-email.me>
In reply to#30919
On 26/01/15 18:05, Robbie Brown wrote:
> On 26/01/15 15:55, Eric Sosman wrote:
>> On 1/26/2015 10:40 AM, John wrote:
>>>
>>> I am amazed at what I saw:
>>>
>>> synchronized private void print()
>>> {
>>>       System.out.println("printing A");
>>>       System.out.println("printing B");
>>>       System.out.println("printing C");
>>> }
>>> [... he gets interleaved output ...]
>>
>>      Each Java object has its own lock ("monitor"), independent of the
>> locks belonging to other Java objects.  When you call a synchronized
>> instance method, Java acquires the lock of the "this" object before
>> proceeding, and releases it when the method finishes.  If there are
>> several object instances floating around, there are several "this"
>> and several independent locks.
>>
>>> I thought the method is atomic.
>>
>>      No.  Synchronization is not about methods (or code blocks), but
>> about objects: You lock the *object*, not a method.
>
> Are you sure?
>
> If you have a class with two methods and one (or more) of them is
> synchronized and one (or more) isn't then a thread can obtain the lock
> on an instance of that class which locks out all other threads from the
> synchronized methods but the non synchronized methods of that instance
> are still available to other threads.
>
> At least that's how I remember it.

Ooops that should have read "If you have a class with *several* methods ..."


-- 
Not floundering ... just fishing

[toc] | [prev] | [next] | [standalone]


#30933

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-01-26 17:19 -0500
Message-ID<ma6ehc$rdm$1@dont-email.me>
In reply to#30920
On 1/26/2015 1:08 PM, Robbie Brown wrote:
> On 26/01/15 18:05, Robbie Brown wrote:
>> On 26/01/15 15:55, Eric Sosman wrote:
>>> On 1/26/2015 10:40 AM, John wrote:
>>>>
>>>> I am amazed at what I saw:
>>>>
>>>> synchronized private void print()
>>>> {
>>>>       System.out.println("printing A");
>>>>       System.out.println("printing B");
>>>>       System.out.println("printing C");
>>>> }
>>>> [... he gets interleaved output ...]
>>>
>>>      Each Java object has its own lock ("monitor"), independent of the
>>> locks belonging to other Java objects.  When you call a synchronized
>>> instance method, Java acquires the lock of the "this" object before
>>> proceeding, and releases it when the method finishes.  If there are
>>> several object instances floating around, there are several "this"
>>> and several independent locks.
>>>
>>>> I thought the method is atomic.
>>>
>>>      No.  Synchronization is not about methods (or code blocks), but
>>> about objects: You lock the *object*, not a method.
>>
>> Are you sure?
>>
>> If you have a class with two methods and one (or more) of them is
>> synchronized and one (or more) isn't then a thread can obtain the lock
>> on an instance of that class which locks out all other threads from the
>> synchronized methods but the non synchronized methods of that instance
>> are still available to other threads.
>>
>> At least that's how I remember it.
>
> Ooops that should have read "If you have a class with *several* methods

     We're both speaking a bit informally, and this is perhaps why we
appear to disagree even if we probably don't.  Let me try to be a
little more precise, at the risk of possibly confusing the O.P. to whom
my original informal language was directed:

     A method or code block that is synchronized must lock the monitor
of some object instance before starting execution, and must unlock it
on normal or abrupt completion.  If the instance's monitor is already
locked by a different thread, the attempt to re-lock it stalls and the
attempting thread waits for a later opportunity.

     The monitor is locked and released by code, but it belongs to the
object instance.  That implies a couple of things:

     - Two different threads can execute the same synchronized method
       or code block if they synchronize on different object instances.
       (This was the case that surprised the O.P.)  If the "this" in
       thread T1 is the red object and "this" in T2 is the blue object,
       both T1 and T2 can execute `synchronized makeHay()' at the same
       time: The red and blue objects' monitors don't interfere.

     - Two different threads can get in each other's way by executing
       different methods synchronized on the same object instance.
       If threads T1 and T2 both have a "this" that refers to the
       orange object, then T1 cannot run `synchronized makeHay()'
       at the same time that T2 runs `synchronized makeWhoopee()'.
       Even though makeHay() and makeWhoopee() are distinct methods,
       they cannot run at the same time on the same object.

... and that's what I meant by synchronization pertaining to objects,
not to code.

     You're quite right that synchronization does not interfere with
unsynchronized code.  Holding an object's monitor does not prevent all
uses of that object, only those that attempt to lock the same monitor.
If that's what you thought I meant, I didn't and I'm sorry for leading
you astray.

     For completeness: Even a static method can be synchronized, even
though there's no "this" object to synchronize on.  What happens is
that it synchronizes on its own class' Class object.  Thus, all static
synchronized methods of one class lock each other out (which is sort
of what the O.P. was expecting for instance methods), but it's still
not about code blocking code: It's about whether the Class object's
monitor is or isn't already locked.

     For even more completeness: When a thread locks an object's
monitor, it prevents *other* threads from locking that monitor.  The
thread that already owns the lock can acquire it a second time, or
a third, fourth, ..., time; `synchronized makeHay()' can call
`synchronized makeWhoopee()' without danger of self-deadlock.  The
monitor is finally unlocked when the owning thread performs as many
releases as acquisitions, unwrapping as many layers of lock as it
applied.  Again, it's the state of the monitor that matters, not the
identity of the code.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#30923

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-01-26 13:27 -0500
Message-ID<54c686fe$0$288$14726298@news.sunsite.dk>
In reply to#30919
On 1/26/2015 1:05 PM, Robbie Brown wrote:
> On 26/01/15 15:55, Eric Sosman wrote:
>> On 1/26/2015 10:40 AM, John wrote:
>>>
>>> I am amazed at what I saw:
>>>
>>> synchronized private void print()
>>> {
>>>       System.out.println("printing A");
>>>       System.out.println("printing B");
>>>       System.out.println("printing C");
>>> }
>>> [... he gets interleaved output ...]
>>
>>      Each Java object has its own lock ("monitor"), independent of the
>> locks belonging to other Java objects.  When you call a synchronized
>> instance method, Java acquires the lock of the "this" object before
>> proceeding, and releases it when the method finishes.  If there are
>> several object instances floating around, there are several "this"
>> and several independent locks.
>>
>>> I thought the method is atomic.
>>
>>      No.  Synchronization is not about methods (or code blocks), but
>> about objects: You lock the *object*, not a method.
>
> Are you sure?
>
> If you have a class with two methods and one (or more) of them is
> synchronized and one (or more) isn't then a thread can obtain the lock
> on an instance of that class which locks out all other threads from the
> synchronized methods but the non synchronized methods of that instance
> are still available to other threads.
>
> At least that's how I remember it.

I think that is what Eric is saying.

It may have been more clear by phrasing it like
"you lock *on* an object".

Arne

[toc] | [prev] | [next] | [standalone]


#30928

FromRobbie Brown <rob@example.com>
Date2015-01-26 19:51 +0000
Message-ID<ma65qf$tlm$1@dont-email.me>
In reply to#30923
On 26/01/15 18:27, Arne Vajhøj wrote:
> On 1/26/2015 1:05 PM, Robbie Brown wrote:
>> On 26/01/15 15:55, Eric Sosman wrote:
>>> On 1/26/2015 10:40 AM, John wrote:
>>>>
>>>> I am amazed at what I saw:
>>>>
>>>> synchronized private void print()
>>>> {
>>>>       System.out.println("printing A");
>>>>       System.out.println("printing B");
>>>>       System.out.println("printing C");
>>>> }
>>>> [... he gets interleaved output ...]
>>>
>>>      Each Java object has its own lock ("monitor"), independent of the
>>> locks belonging to other Java objects.  When you call a synchronized
>>> instance method, Java acquires the lock of the "this" object before
>>> proceeding, and releases it when the method finishes.  If there are
>>> several object instances floating around, there are several "this"
>>> and several independent locks.
>>>
>>>> I thought the method is atomic.
>>>
>>>      No.  Synchronization is not about methods (or code blocks), but
>>> about objects: You lock the *object*, not a method.
>>
>> Are you sure?
>>
>> If you have a class with two methods and one (or more) of them is
>> synchronized and one (or more) isn't then a thread can obtain the lock
>> on an instance of that class which locks out all other threads from the
>> synchronized methods but the non synchronized methods of that instance
>> are still available to other threads.
>>
>> At least that's how I remember it.
>
> I think that is what Eric is saying.

Really?

"No.  Synchronization is not about methods (or code blocks), but
about objects: You lock the *object*, not a method"

seems pretty clear to me. 'still, I'm sure you know best.


-- 
Not floundering ... just fishing

[toc] | [prev] | [next] | [standalone]


#30948

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2015-01-28 21:55 +0200
Message-ID<lv4mra65p1.fsf@saunalahti.fi>
In reply to#30912
John <xsli2@yahoo.com> writes:

> synchronized private void print()
> {
>      System.out.println("printing A");
>      System.out.println("printing B");
>      System.out.println("printing C");
> }

Like others said, this will lock on the individual object, the instance
of the class that defines the print() method, and if you have two
instances of that class, they can execute the method without blocking
each other. And one way of preventing different threads is to make the
method static.

However, if you need to use instance variables in the method or
for some other reason can't make the method static, you can define a
static lock object and synchronize a code block on that, as long as the
threads run on the same JVM.
This way (I didn't test this snippet now, so there may be some bug, but
it should work something like this):

private static final Object synchroLock = new Object();

private void print() {
  // possibly some code that will not be synchronized
  synchronized (synchroLock) {
    System.out.println("printing A");
    System.out.println("printing B");
    System.out.println("printing C");
  }
  // possibly some more code that will not be synchronized
}

You must make the synchroLock object static, so it CAN be shared with
all instances of the class, and you should make it final to make sure
that it can't be instantiated after the classloader instantiates it.
If the synchroLock gets instantiated again, the synchronization will not
work between class instances having separate instances of synchroLock.

-- 
Jukka Lahtinen

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web