盒装原语上的同步 [英] Synchronization on boxed primitive
问题描述
我是多线程编程的新手.因此,我需要一些帮助来解决这个问题.我在框式原语上发现了一个带有同步的findbugs错误:
I am new to multithreaded programming. So I need some help to this issue. I get a findbugs bug with synchronization on a boxed primitive:
http://findbugs.sourceforge.net/bugDescriptions.html#DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE
我在此站点上尝试了一些解决方案,但它没有按预期工作.有时我会从findbugs得到类似的错误.
I tried some solutions on this site but it doesn't work as I expected. Sometimes I get a similar error from findbugs.
我的代码需要对我传递给构造函数的id进行锁定,这是一些伪代码:
My code needs a lock on a id which I pass to a constructor, here is some pseudocode:
public class MyClass{
public MyClass(long id){
synchronized(id){
// do some stuff
}
}
}
问题是,只有具有相同ID的线程才应在同步块上进行阻塞.具有不同ID的线程应同时工作.
The problem is, that only threads with the same id should block on the synchronized block. Threads with different ids should work simultaneously.
我也尝试过类似的方法,但是它对我不起作用:
I also tried something like this, but it doesn't work for me:
public class MyClass{
private static final ConcurrentHashMap<Long, Object> myHashMap = new ConcurrentHashMap<Long, Object>();
public MyClass(long id){
Object object = getObject(id);
synchronized(object){
// do some stuff
}
}
private Object getObject(long id){
if(!myHashMap.contains(id)){
writeObject(id);
}
return myHashMap.get(id);
}
private synchronized void writeObject(long id){
if(!myHashMap.contains(id)){
myHashMap.put(id, new Object());
}
}
}
在您看到的第二个示例中,我尝试将每个id的对象放入哈希图中,但是 我意识到一个单元测试,具有相同id的线程进入了同步块.但是他们不应该这样做.如果有人有其他解决方案或如何解决这些问题,我将非常感激.
In the second example you see, I tried to put an object per id in the hashmap, but with an unit test I realized, that threads with same id get in the synchronized block. But they should not do. I will be very thankful if someone has another solution or how to handle these problems.
推荐答案
编写单元测试对您有好处!供将来参考:您想测试所有类型的边值,这意味着对于至少0,-1、1,MAX_VALUE,MIN_VALUE的数字,这将捕获您错过的第二个错误:-)
Good for you that you wrote an unit test! For future reference: You want to test all kinds of edge values, which means for numbers at least 0, -1, 1, MAX_VALUE, MIN_VALUE - that would've caught the second bug you missed :-)
您的代码存在的问题是:synchronized(l) {}
转换为:synchronized(Long.valueOf(l)){}
. valueOf
缓存Longs的值在-128,127范围内,但这甚至是可选的(JLS令人惊讶地仅要求整数!).因此,一旦您的ID大于127,您的整个方案就会崩溃.
The problem with your code is that: synchronized(l) {}
translates to: synchronized(Long.valueOf(l)){}
. valueOf
caches Longs in the range -128, 127 but even this is optional (the JLS only requires it for integers surprisingly!). Consequently as soon as your ids are larger than 127 your whole scheme falls apart.
第二种方法是可行的方法,但是您不能仅使方法同步-只会在this
上同步,因此不能保证静态映射的原子性.
Your second method is the way to go, but you cannot just make the method synchronized - that will just synchronize on this
, so doesn't guarantee atomicity for the static map.
相反,请执行以下操作:
Instead do something like this:
Object newLock = new Object();
Object oldLock = map.putIfAbsent(id, newLock);
Object lock = oldLock != null ? oldLock : newLock;
synchronized(lock) {
}
这篇关于盒装原语上的同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!