这个问题基于 Synchronizing on an Integer value。
那里的解决方案似乎很好,只是有一个小问题,它没有解决如何从ConcurrentHashMap
.
所以为了解决我在下面的程序中所做的
import java.util.concurrent.ConcurrentHashMap;
public class Example {
private final ConcurrentHashMap<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<Integer, Integer>();
public void doSomething(int i) {
synchronized (getLockForId(i)) {
concurrentHashMap.remove(i);
}
}
public Integer getLockForId(int id) {
concurrentHashMap.putIfAbsent(id, id); // I want to replace these two
// operation with single one
// since it seems the cause of
// NPE
return concurrentHashMap.get(id);
}
public static void main(String[] args) {
final Example example = new Example();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
example.doSomething(++i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
example.doSomething(++i);
}
}
}).start();
}
}
问题是它总是导致NullPointerException
. 我的第一个分析是因为我正在删除它分配给 null 的值,所以它导致NullPointerException
. 所以我在下面做了
Object obj = new Object();
synchronized (obj) {
obj = null;
}
但以上不会导致NullPointerException
. 所以我的问题是为什么它会抛出NullPointerException
上述情况?
即使我这样做
public Integer getLockForId(int id) {
return concurrentHashMap.putIfAbsent(id, id);
}
它仍然会导致,NullPointerException
因为它仅在有 else 返回时才返回值null