Sorry if this is very obvious or answered elsewhere. I could not find anything. I have the following code:
public class SimpleThread extends Thread { public static Integer sharedVal = 0; public SimpleThread() { } @Override public void run() { while(true) { iterator(); } } public void theSleeper() { System.out.println("Thread: " + this.getId() + " is going to sleep!"); try { this.sleep(5000); } catch(Exception e) { } } public void iterator() { synchronized(sharedVal) { System.out.println("Iterating sharedVal in thread: " + this.getId()); sharedVal++; System.out.println(sharedVal); theSleeper(); System.out.println("Thread : " + getId() + " is done sleeping, trying to iterate again..."); } } }
I create two instances of this SimpleThread class and execute the launch methods. I would expect to see something like: Thread 9 incrementing ... Thread 9 sleeping ... (after 5 seconds) Thread 10 increases ... Thread 10 sleep .... I expect this because I am blocking the iterator method, so only one thread at a time should be able to enter it. Instead, both threads increase and then both wait 5 seconds. This is repeated forever. What am I missing here to get the expected behavior? Thank you very much!
EDIT: I created a new public static variable: public static Object theLock = new Object (). Now, in the iterator method, I am doing the synchronization (theLock). The result is now larger as I expected, because the lock never changes. However, now only method 9 is always included in this method. Thread 10 seems to be starving and never getting a turn. That seems weird. This is not just a few times, its always just a thread of 9, iteration and sleep. I think it will be 9, 10, 9, 10. Or, perhaps, a random distribution, for example 9, 10, 10, 10, 9, 10, 9, 9, 10, etc.
EDIT2: I see what is happening now. Thread 9 has a lock. Topic 10 tries to enter the function, but is immediately invited to wait. Upon completion of the function, Thread 9s may still be included. Then thread 9 causes a lock, and the loop continues. The time window for thread 10 to get a rotation is very small, and if it got a rotation, it could probably starve 9. Saying this, adding yield () after the synchronized block in iterator () does not seem to makes it more fair. I read the comments on the method, and the scheduler can actually ignore yield ().