This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Doubt in  one question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Doubt in  one question" Watch "Doubt in  one question" New topic
Author

Doubt in one question

Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

Hi,

I have a small doubt just go through it.

Source : Kathy Sierra page 745

public class Letters extends Thread {
private String name;
public Letters(String name) { this.name = name; }
public void write() {
System.out.print(name);
System.out.print(name);
744 Chapter 9: Threads
}
public static void main(String[] args) {
new Letters("X").start();
new Letters("Y").start();
} }
We want to guarantee that the output can be either XXYY or YYXX, but never XYXY or any
other combination. Which of the following method definitions could be added to the Letters
class to make this guarantee? (Choose all that apply.)
A. public void run() { write(); }
B. public synchronized void run() { write(); }
C. public static synchronized void run() { write(); }
D. public void run() { synchronized(this) { write(); } }
E. public void run() { synchronized(Letters.class) { write(); } }
F. public void run() { synchronized(System.out) { write(); } }
G. public void run() { synchronized(System.out.class) { write(

one of the option that is correct is:
E. public void run() { synchronized(Letters.class) { write(); } }

But its not clear to me because putting synchronized on Letters.class will give lock to the class it means only static methods are synchronized but write() method is not static.
I think acquiring a lock on class will also acquire lock on any static variable belongs to that class or the outside class like System.out

Please explain me if I am wrong.


Thanks,

Abdul Mohsin


Regards, Abdul Mohsin
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
The main issue with this question is that, there are two thread object, each can independently execute there methods without blocking each other, if we don't apply the technique of static lock (that is one for each class), we wont get the desirable result.



E is correct because before there is only class lock. So while a thread acquires the class lock it will block all other threads even trying to get the sync block on different objects. Because there is one and only class lock; only one thread can execute that sync block (synchronized on class)
and ofcourse come out only after completing the code within that block.




F is true because System.out is a static reference, and a thread that is holding the lock of System.out can only use enter into the block to execute
write() method.

So in other words no any System.out.print statement can be executed because out is blocked by another thread.

We can't guarantee though whether it would be XX YY of YY XX, because it depends which thread has acquired the lock first.


Thanks,
[ May 07, 2007: Message edited by: Chandra Bhatt ]

cmbhatt
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
>> I think acquiring a lock on class will also acquire lock on any static variable belongs to that class or the outside class like System.out

Class in this case is "Class object", so the rules should be same as for objects.

Lock is acquired on the whole object, but this doesn't prevent anyone from directly manipulating with your variables (outside synchronized context).

Example below demonstrates, that you can directly manipulate static member, whilst another thread owns lock on that class's "Class object".

Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

its still not clear to me

suppose acquiring a lock on Class will give locks of its static variables also it means when thread one is executing
System.out.print(name);
Thread 2 is not allowed to execute this line but..
after completion of this line thread 1 will lose the lock and thread 2 can execute this line before thread 1 will execute futher lines.
So in that case output would not be XX YY or YY XX

Please help

Regards,
Abdul Mohsin
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
The other threads are not allowed to acquire lock on some object (O) as long as you are in synchronised (O) block.



means, that Thread 1 owns lock on object (Letters.class), and until this entire block is finished (including executing println twice), no other thread will be able to acquire lock on Letters.class object and therefore cannot execute content of synchronized block.

Your lock on object (O) is valid until the whole synchronised (O) block is finished.
Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

Thanks John but....
you mean to say acquiring lock on Letters

synchronized(Letters.class)


will acquire lock not only on static methods or variable but on non static also, am I right?

Generally acquiring lock on .class will synchronized only static methods but in this case its different.

Regards,

Abdul Mohsin
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Hi,


John said,
that you can directly manipulate static member, whilst another thread owns lock on that class's "Class object".


About System.out lock:




Output:
>0< //Line #1
>1<
>1<
>1<
>1<
>1<
>1<
>1<
>1<
>1<
0 //Line #2
1
2
3
4
5
6
7
8
9
10
11
12
13
14


I agree with you, and what my observation says, while there was lock on System.out what tiger thread acquired, at the same time Hunter thread incremented the static variable and it was executed inside the
System.out.println statement but there is is a lock on that object so it couldn't print that, and blocked there, now the Tiger thread completes and then Hunter thread starts printing from where it was blocked, I mean from 0 onwards.




Thanks,
[ May 07, 2007: Message edited by: Chandra Bhatt ]
Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

Hi

But in my case we are acquiring lock on .class and not on System.out, I agree that if we put lock on System.out then it will give correct results but how come acquiring lock on .class will synchronized System.out present in non static method.

Regards,

Abdul Mohsin
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707

Abdul said,

...but how come acquiring lock on .class will synchronized System.out present in non static method.



They are two different locks, they wont block each other.
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
synchronized("someObject") will acquire lock on object "someObject" before entering block of code or method.

AFAIK, there is no such thing as acquire lock on methods, or acquire lock on primitve variables. Also you can't acquire lock on class.

If somebody owns lock on my object, then I can't use any synchronized methods or any synchronized blocks of code which are trying to acquire lock on my object. But I still can use non-synchronized methods, and still can run synchronized blocks, which are acquiring locks on other object than mine.

Letters.class gives you _object_ of type Class, it is instance of class "Class"

If somebody (some thread) acquires lock on your object, it doesn't mean, that your methods are automatically thread-safe. If your methods are not "synchronized", then you are saying, that "This method can be run without acquiring lock on this object".

Please take a look at code below. You can see, that thread A1 acquired lock on unsafeObject, but this doesn't prevent A2 from calling it. The access method is executing until it tries acquire to lock on itself (this lock is owned by A2 at the moment), so it must wait, until A2 releases it. After that, it can continue with the rest of access method.


John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
>> System.out.println statement but there is is a lock on that object so it couldn't print that,

<deleted by John>
[ May 07, 2007: Message edited by: John Stone ]
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
Originally posted by Abdul Mohsin:
Hi

But in my case we are acquiring lock on .class and not on System.out, I agree that if we put lock on System.out then it will give correct results but how come acquiring lock on .class will synchronized System.out present in non static method.

Regards,

Abdul Mohsin


synchronized(Letters.class) { write(); }

1. There is only one object "Letter.class" (of type Class).
2. Only 1 thread can own lock on this object at a time.
3. So if one thread start executing synchronized block (with non-static write()), the other thread must wait, because of 2.

the "synchronized" keyword will cause, that code between "{" and "}" is synchronized (by object Letters.class lock).

Let's say, there is third thread, which calls:

you can see on output "XXWYY" or "XWXYY" or "XXYWYW" or ...

System.out is not locked in this case, therefore anyone can use it any time.
Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

Thanks to john and chandra,
Now everything is very clear to me.

Regards,

Abdul Mohsin
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
John,

Yo took my factor in another way, I said, because one thread has acquired a lock on the System.out so no other thread could execute System.out because there is one and only lock of System.out.

In my example because tiger thread has acquired the lock and if meanwhile the hunter thread comes to S.O.P line (Tiger.n++ will be executed first obviously)
but S.O.P could not complete because the lock of System.out is in the hand of Tiger thread. Hunter S.O is blocked and Tiger completes and when it leaves the lock the Hunter thread starts by printing 0,1,2,3....

But if you see the code, Tiger thread prints >1<, >1< ,. .. and so.
But when Hunter S.O starts it starts printing from 0 the last it was not able to complete.
Abdul Mohsin
Ranch Hand

Joined: Apr 26, 2007
Posts: 111

ones again thanks john for showing such patience


Thanks,

Abdul Mohsin
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
Chandra,

I think you are right,.. I said, that println methods are not synchronized. I just took a look at code, and they are all synchronized :-)

from PrintStream.java:


But if this "synchronized" was missing your output will look much different, because Tiger is having lock on System.out, but println methods wouldn't care :-) and print anyway.

If Tiger owns lock on System.out, you can't execute any synchronized method on System.out
System.out.syncmethod(); // wait here for lock on System.out

but you can execute any other unsychronized method. (This is what I meant)
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Nice John,

Did you consider the output from my code where I marked output as Line #1 and Line #2. I would like to get the reason for that sequence from you.

I get it from you that, if print etc method were not synchronized, the story would be something different.



Thanks,
John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
Take a look at this code:

Here we have our own version of System, called System2 :-),
if Hunter is using synchronized version System2.out.println, it looks exactly like your output.

But, if Hunter is using System2.out.unsync_println, this method is not waiting until lock on System2.out is release, it just ignores it and print right away.

John Stone
Ranch Hand

Joined: May 04, 2007
Posts: 332
Originally posted by Chandra Bhatt:
Nice John,

Did you consider the output from my code where I marked output as Line #1 and Line #2. I would like to get the reason for that sequence from you.



Yes, I see nothing wrong with that output.

Tiger gets lock on System.out and start his printing,
Hunter is also trying to get lock on System.out, but is is already locked, so it can't start executing println. However JLS says, that arguments are evalueted before operation (method call), so value i gets incremented, but here it stops until Hunter gets lock on System.out.
When Tiger finishes his printing, Hunter continues with entering println with value 0 saved on stack.

This would be interesting to try with some object, so the reference will be kept on stack and the real value accessed immeadiately before printing.
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Done!

Thanks John!

It was really very long discussion on synchronization issue that finally concluded very fine, alleviating all the doubts.


Thanks again for your patience and very prompt replies with nice examples.
[ May 07, 2007: Message edited by: Chandra Bhatt ]
 
Don't get me started about those stupid light bulbs.
 
subject: Doubt in one question
 
Similar Threads
Thread doubt
Q 2 pg 744 Threads Doubt
scjp self test on thread doubt
Question on thread q.2 pg 734
K&C book Threads doubt in Exercise question#2