Why is the synchronized method not synchronized in this multi-threaded program?

I wrote some multi-threaded code in Java and a synchronized method that changed the variable, but it did not synchronize my code, I still get random values. There is my code:

public class Main { public static void main(String[] args) throws Exception { Resource.i = 5; MyThread myThread = new MyThread(); myThread.setName("one"); MyThread myThread2 = new MyThread(); myThread.start(); myThread2.start(); myThread.join(); myThread2.join(); System.out.println(Resource.i); } } class MyThread extends Thread { @Override public void run() { synMethod(); } private synchronized void synMethod() { int i = Resource.i; if(Thread.currentThread().getName().equals("one")) { Thread.yield(); } i++; Resource.i = i; } } class Resource { static int i; } 

Sometimes I get 7, sometimes 6, but I synchronized synMethod , since I understand that no thread should go through this method while some other thread does this, so the operations should be atomic, but they are not, and I canโ€™t understand why? Could you explain this to me and answer - how can I fix it?

+5
source share
2 answers

Adding a synchronized method is similar to synchronizing to this . Since you have two different instances of threads, they do not block each other, and this synchronization actually does nothing.

For the synchronization to take effect, you need to synchronize with some kind of shared resource. In your example, Resource.class might be a good choice:

 private void synMethod() { // Not defined as synchronized // Synchronization done here: synchronized (Resource.class) { int i = Resource.i; if (Thread.currentThread().getName().equals("one")) { Thread.yield(); } i++; Resource.i = i; } } 
+10
source

Let's look at the definition of synchronized methods on the oracle documentation page.

Creating synchronized methods has two effects:

First, it is not possible for two calls of synchronized methods on the same object to alternate. When one thread executes a synchronized method for an object, all other threads that invoke synchronized methods for the same object (pause execution) until the first thread executes with the object.

Returning to your request:

synMethod() is the level of the object with the synchronized object. Two threads accessing the same synchronized method receive an object lock in a sequential manner. But two threads accessing the synchronous method of different instances (objects) are started asynchronously in the absence of a common lock.

myThread and myThread2 are two different objects => Internal locks are acquired in two different objects, and therefore you can access these methods asynchronously.

One solution: as stated in Mureinik, use a shared object to lock.

Another solution: use better concurrency constructs like ReentrantLock etc.

You will find several alternatives in the SE related question:

Avoid syncing (this) in Java?

+1
source

All Articles