Java Synchronized

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 ().

+6
source share
4 answers

Your problem is here:

 sharedVal++; 

This line due to autoboxing translates as follows:

 sharedVal = Integer.valueOf(sharedVal.intValue() + 1); 

which creates a new Integer object every time it starts, so every time a synchronized block is executed, it blocks a different value.

Use the selected object to synchronize:

 private final static Object LOCK = new Object(); 

and then change the synchronization to use synchronized (LOCK) {... instead.

(You can also use getClass() to lock, but I personally don’t like opening lock objects for the public world)

+3
source

When you increment, you create a new integer instance and a new object to lock.

+5
source

You effectively change the lock that threads use at each iteration: ++ in Integer creates a new instance (the Integer class is immutable)

+1
source

shareval member varible instance changes when sharedVal ++ is executed. Instead, you can use the following statement to synchronize:

synchronized (SympleThread.class)

0
source

Source: https://habr.com/ru/post/957367/


All Articles