我正在尝试遵循ReentrantLock Example in Java, Difference between synchronized vs ReentrantLock这种教程。我有一个以-ea
开头的演示,
public class ReentrantLockZero {
private static ReentrantLock CountLock = new ReentrantLock();
private static int count = 0;
private static final int RESULT_COUNT = 10_000;
public static void main(String... args) throws Exception {
ThreadPoolExecutor threadPoolExecutor = getMyCachedThreadPool();
for (int i = 0; i < RESULT_COUNT; ++i) {
threadPoolExecutor.submit(ReentrantLockZero::getCount);
threadPoolExecutor.submit(ReentrantLockZero::getCountUsingLock);
}
threadPoolExecutor.shutdown();
threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS);
assert count == RESULT_COUNT * 2;
}
private static synchronized int getCount() {
count++;
System.out.println(Thread.currentThread().getName() + " counting in synchronized: " + count);
return count;
}
private static int getCountUsingLock() {
CountLock.lock();
try {
count++;
System.out.println(Thread.currentThread().getName() + " counting in lock: " + count);
return count;
} finally {
CountLock.unlock();
}
}
}
使用ReentrantLock
作为第二种方法getCountUsingLock
时,我会得到java.lang.AssertionError
,但是当我注释掉它们以使用synchronized
时,这是可以的。
考虑到其 Re entrantLock,我删除了在类中定义的CountLock
并按以下方式使用本地锁,但仍然无法正常工作。
private static int getCountUsingLock() {
ReentrantLock countLock = new ReentrantLock();
countLock.lock();
try {
count++;
System.out.println(Thread.currentThread().getName() + " counting in lock: " + count);
return count;
} finally {
countLock.unlock();
}
}
这里遗漏了什么?
任何帮助将不胜感激;)
答案 0 :(得分:2)
那种傻瓜。
之所以这样工作,是因为我实际上锁定了其他对象。
private static synchronized int getCount()
等于
private static synchronized (ReentrantLockZero.class) int getCount()
而new ReentrantLock();
始终是一个新对象,无法使用不同的锁来消除race condition。
我这个傻瓜,可以通过以下演示轻松修复
public class ReentrantLockZero {
private static ReentrantLock CountLock = new ReentrantLock();
private static int synchronisedCount = 0;
private static int lockedCount = 0;
private static final int RESULT_COUNT = 10_000;
public static void main(String... args) throws Exception {
ThreadPoolExecutor threadPoolExecutor = getMyCachedThreadPool();
for (int i = 0; i < RESULT_COUNT; ++i) {
threadPoolExecutor.submit(ReentrantLockZero::getSynchronisedCount);
threadPoolExecutor.submit(ReentrantLockZero::getCountUsingLock);
}
threadPoolExecutor.shutdown();
threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS);
assert synchronisedCount == RESULT_COUNT;
assert lockedCount == RESULT_COUNT;
}
private static synchronized int getSynchronisedCount() {
synchronisedCount++;
System.out.println(Thread.currentThread().getName() + " counting in synchronized: " + synchronisedCount);
return synchronisedCount;
}
private static int getCountUsingLock() {
CountLock.lock();
try {
lockedCount++;
System.out.println(Thread.currentThread().getName() + " counting in lock: " + lockedCount);
return lockedCount;
} finally {
CountLock.unlock();
}
}
}
synchronized
为什么起作用?因为那时只有一个锁,所以这两种方法都处于锁定状态,因此竞争条件可以直接解决。
容易被本教程所欺骗;对我感到羞耻;(