Java同步块使用方法调用获取同步对象 [英] Java synchronized block using method call to get synch object

查看:97
本文介绍了Java同步块使用方法调用获取同步对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在编写一些锁定代码,并且遇到了一个特殊的问题。我们使用ConcurrentHashMap来获取锁定的Object的实例。因此我们的同步块如下所示:

We are writing some locking code and have run into a peculiar question. We use a ConcurrentHashMap for fetching instances of Object that we lock on. So our synchronized blocks look like this

synchronized(locks.get(key)) { ... }

我们重写了ConcurrentHashMap的get方法,使其始终返回一个新对象(如果该对象不包含密钥)。

We have overridden the get method of ConcurrentHashMap to make it always return a new object if it did not contain one for the key.

@Override
public Object get(Object key) {
   Object o = super.get(key);
   if (null == o) {
      Object no = new Object();
      o = putIfAbsent((K) key, no);
      if (null == o) {
         o = no;
      }
   }
   return o;
}

但是在某种状态下,get方法已返回对象,但是线程尚未进入同步块。允许其他线程获取相同的对象并将其锁定。

But is there a state in which the get-method has returned the object, but the thread has not yet entered the synchronized block. Allowing other threads to get the same object and lock on it.

我们有一个潜在的竞争条件是

We have a potential race condition were


  • 线程1:获取具有键A的对象​​,但不输入同步块

  • 线程2:获取具有键A的对象​​,输入一个同步块

  • 线程2:从地图中删除对象,退出同步块

  • 线程1:使用不再位于对象中的对象进入同步块map

  • 线程3:获取密钥A的新对象(与线程1获得的对象不同)

  • 线程3:输入同步块,而线程1也在其同步块中,都使用键A

  • thread 1: gets the object with key A, but does not enter the synchronized block
  • thread 2: gets the object with key A, enters a synchronized block
  • thread 2: removes the object from the map, exits synchronized block
  • thread 1: enters the synchronized block with the object that is no longer in the map
  • thread 3: gets a new object for key A (not the same object as thread 1 got)
  • thread 3: enters a synchronized block, while thread 1 also is in its synchronized block both using key A

get的调用返回后。如果没有,是否有人对我们如何删除密钥而不必担心这种竞争状况有任何意见?

This situation would not be possible if java entered the synchronized block directly after the call to get has returned. If not, does anyone have any input on how we could remove keys without having to worry about this race condition?

推荐答案

2个选项:

a。您可以在同步块内检查一次地图。

a. you could check the map once inside the synchronized block.

Object o = map.get(k);
synchronized(o) {
  if(map.get(k) != o) {
    // object removed, handle...
  }
}

b。您可以扩展值以包含一个指示其状态的标志。当从地图中删除某个值时,可以设置一个标志,指示该值已删除(在同步块内)。

b. you could extend your values to contain a flag indicating their status. when a value is removed from the map, you set a flag indicating that it was removed (within the sync block).

CacheValue v = map.get(k);
sychronized(v) {
  if(v.isRemoved()) {
    // object removed, handle...
  }
}

这篇关于Java同步块使用方法调用获取同步对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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