sorry if this is extremely obvious or has been answered elsewhere. I haven't been able to 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 run methods. I would expect to see something like: Thread 9 incrementing... Thread 9 sleeping... (after 5 seconds) Thread 10 incrementing.... Thread 10 sleeping... . I expect this because I am locking the iterator method so that only one thread at a time should be able to enter it. What happens instead is that both threads increment, and then both wait 5 seconds. This repeats forever. What am I missing here such that I would get the expected behavior? Thanks very much!
EDIT: I made a new public static variable: public static Object theLock = new Object(). Now, in the iterator method, I do synchronized(theLock). The output is now more as I expected, because the lock never changes. However, now only thread 9 ever enters the method. It seems that thread 10 is starving, and never gets a turn. This seems strange. It's not just a few times, its always just thread 9 iterating and sleeping. I would think that it would be 9, 10, 9, 10. Or perhaps a random distribution like 9, 10, 10, 10, 9, 10, 9, 9, 10, etc.
EDIT2: I see what's happening now. Thread 9 has the lock. Thread 10 tries to enter the function, but is immedietly told to wait. After the function completes, it may still be Thread 9s turn. Thread 9 then reaqquires the lock, and the cycle continues. The timing window for thread 10 to get a turn is very small, and if it did get a turn it would likely starve 9. That being said, putting yield() after the synchronized block in iterator() does not seem to make it more fair. I read the comments on the method, and the scheduler can in fact ignore yield().
When you are doing increment you create a new instance of integer and a new object for locking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With