Given:
5. class NoGo implements Runnable {
6. private int i;
7. public synchronized void run() {
8. if (i%10 != 0) { i++; }
9. for(int x=0; x<10; x++, i++)
10. { if (x == 4) Thread.yield(); }
11. System.out.print(i + " ");
12. }
13. public static void main(String [] args) {
14. NoGo n = new NoGo();
15. for(int x=0; x<101; x++) { new Thread(n).start(); }
16. }
17. }
Which is true?
a The output can never contain the value 10.
b The output can never contain the value 30.
c The output can never contain the value 297.
d The output can never contain the value 820.
e The output can never contain the value 1010.
No. The correct answer is: (c)
"The output can never contain the value 297"
Explanation:
First of all note that even though the i in the NoGo is an instance variable, all the thread start with the same object (n), so i is shared between 100 thread objects.
As you see at the for loop there is a yield method, and we know that there is no guarantee that a thread run this method and actually yield and go from running state to runnable, so to better understand what the code does, I will explain it in two situation (which both is possible at runtime)
1) Threads do not yield In this case we basically ignore the Thread.yield() line and interpret the code as this line commented. The initial value of i is 0 so the expression i%10 !=0 evaluates to false, so i incremented in the for loop 10 times, then 10 will be printed. Well, same scenario for the rest of threads, we'll have 20, 30, 40,....., 1000. (Since we have 100 thread and each increment the i for 10 times so 10x100=1000) and in all of these the first if condition always evaluate to false.
1) Threads do yield Well, this one is a bit tricky. For the first thread, when thread is going to yield, the i value is 4 since x and i incremented along together equivalently. Ok, thread yields, next thread will come to play with the value of i==4. So this time the first if run and i become 5 and when entering the loop, we have 4 more increments for i to make the value 9 and x==4 then thread yield again and next thread increment the i value in the if to 10 and again 4 more....
The key point is from x=0 to x=4 we have 5 iteration but the increment statement run 4 times, so basically the first if compensate the fifth increment and make the value of the i something divisible by 10. After all the threads yield the first thread go to running state again and execute the 5 more loop iteration it has and print the value of i. So again, we never come across a value of i which is not divisible by 10.
Hope this makes sense... and one last thing: it's a good idea to run the code at least once before answering other's questions in here!
SCJP 6
Sanjay Singhaniya
Greenhorn
Joined: Feb 21, 2009
Posts: 25
posted
0
My bad. I will take care next time.
I shouldn't have sounded so confident in answering the question.
Sanjay Singhaniya
Greenhorn
Joined: Feb 21, 2009
Posts: 25
posted
0
I guess this has to do more with synchronzed keyword than anything else. Since current executing thread is running a sunchronized run() method, its yield would not release the lock and the same thread would be selected to run as other threads are waiting for the same lock it is holding.
Sanjay Singhaniya
Greenhorn
Joined: Feb 21, 2009
Posts: 25
posted
0
To understand my point, please replace Thread.yield() with Thread.Sleep(1000).
To convince yourself that your argument is incorrect, please try following code.
I think that is correct (a thread will not give up any locks it has acquired when yielding.) So this program should print all multiples of 10 for that reason.
All code in my posts, unless a source is explicitly mentioned, is my own.
Morteza Manavi-Parast
Ranch Hand
Joined: Dec 25, 2008
Posts: 66
posted
0
Yes, that's right. I was totally ignored that Synchronized keyword in the run method while I was explaining that code. I think I should have been on cheap drugs!
So, yea the thread yields and since it has the lock other threads will keep waiting state so the same thread will go back to the running state. So basically my first condition "Threads do not yield" will always happen in this case which brings back those results which have mentioned.
Thanks,
Sanjay Singhaniya
Greenhorn
Joined: Feb 21, 2009
Posts: 25
posted
0
Just a note : While giving SCJP exams, if there seems to be complicated logic then always check whether there are some simple Java rules at work.
As my code snippet shows, if the thread are indeed interleaved then the numbers printed need not be either multiple of 5 or 10.
Ruben Soto
Ranch Hand
Joined: Dec 16, 2008
Posts: 1032
posted
0
Sanjay Singhaniya wrote:Just a note : While giving SCJP exams, if there seems to be complicated logic then always check whether there are some simple Java rules at work.
As my code snippet shows, if the thread are indeed interleaved then the numbers printed need not be either multiple of 5 or 10.
Sanjay, your example is nice, but it is completely different from the original example because the run method is not synchronized. When you have multiple threads and no synchronization, pretty much any result is possible (synchronization just limits the possible outcomes slightly )
Sanjay Singhaniya
Greenhorn
Joined: Feb 21, 2009
Posts: 25
posted
0
I killed some more time and made the threads to yield.