Java lock using "private final lock" and synchronized result are not the same

I am trying to write lock and sync code and compare their performance difference.

the code:

public abstract class Task { public abstract int getTotal(); } // Lock test class public class TaskWithLock extends Task implements Runnable { private static int total = 0; private final Lock lock = new ReentrantLock(); public void run() { try { lock.lock(); doSomething(); } finally { lock.unlock(); } } private void doSomething() { total++; } public int getTotal() { return total; } } // Synchronized test class public class TaskWithSync extends Task implements Runnable { private static int total = 0; public void run() { synchronized ("") { doSomething(); } } private void doSomething() { total++; } public int getTotal() { return total; } } // Test class public class Test { public static void main(String[] args) throws Exception { int count = 100000; runTasks(TaskWithLock.class, count); runTasks(TaskWithSync.class, count); } public static void runTasks(Class<? extends Runnable> clazz, int count) throws Exception { List<Thread> list = new ArrayList<Thread>(count); for (int i = 0; i < count; i++) { list.add(new Thread(clazz.newInstance())); } for (int i = 0; i < count; i++) { list.get(i).start(); } for (int i = 0; i < count; i++) { list.get(i).join(); } System.out.println(clazz.getSimpleName() + "Total Result: " + ((Task) clazz.newInstance()).getTotal()); } } 

I understand that the above lock and the synchronized code block must be the same effect, but the result that I run is not the same, the synchronized code is right, it is always 100000, but the lock code is always incorrect, sometimes 99995 or 99997 or another result but it’s not 100,000.

Console:

TaskWithLock Result: 99991

TaskWithSync Result: 100000

I think my code should have some error, or I understand that Lock is wrong, or Lock cannot be used like this.

Please indicate what might be wrong.

+4
source share
2 answers

In the lock version, you use one lock for each instance. This means that each thread has its own lock, which ultimately makes the locks useless because neither of the two threads uses the same lock.

You need to change this to one central lock for all threads. Add static to this line:

 private final Lock lock = new ReentrantLock(); 

therefore he becomes

 private static final Lock lock = new ReentrantLock(); 
+5
source

Since your lock object is on one instance and you are updating a static variable. Therefore, each thread has its own lock, which is completely pointless to use to protect a static variable.

+3
source

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


All Articles