盒装原语上的同步 [英] Synchronization on boxed primitive

查看:102
本文介绍了盒装原语上的同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是多线程编程的新手.因此,我需要一些帮助来解决这个问题.我在框式原语上发现了一个带有同步的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆