JAVA使用随机字符串进行同步

时间:2017-09-18 02:23:09

标签: java multithreading synchronization locking

我有一个关键过程,我必须确保在任何时候都不能处理两个等效的MyObject(可以是不同的实例,但在逻辑上相等)。以下代码演示了这个想法:

public class MyClass {
    public static ConcurrentMap<MyObject, String> concurrentMap = new ConcurrentHashMap<>();
    public void process(MyObject myObject) {
        String id = UUID.randomUUID().toString();
        String existingId = concurrentMap.putIfAbsent(myObject, id);
        synchronized (id) {
            if (existingId == null) {  // no others, start working right away
                // do work
            } else {  // an equivalent myObject is under processing, wait on it
                synchronized (existingId) {
                    // finally can start doing work
                }
            }
        }
    }
}

上面的代码在随机字符串的synchronized的帮助下工作。但是这段代码的问题是

  1. 每次创建新的随机ID,但如果现有ID已链接到等效的MyObject,则不使用。这种id的唯一目的是充当由另一个线程发现的唯一锁。想一想这是否可以被一些实际的锁定对象取代?

  2. 这段代码中没有办法知道什么时候应该从concurrentMap中删除MyObject,虽然这不会影响结果,但如果concurrentMap保持增长可能不会很好。想在这里可以使用类似锁的计数器吗?

  3. 谢谢

2 个答案:

答案 0 :(得分:2)

我不认为我真的理解这个想法的用例,这是一个大红旗。但在我看来,所有这些代码都是不必要的。如果此处唯一的想法是获取myObject的唯一锁定,那么您已经拥有:myObject

public class MyClass {

    public void process(MyObject myObject) {
       synchronized (myObject) {
           // finally can start doing work
       }
    }
}

剩下的代码就是自重。

然而,这仍然很充实。由于您依赖外部过程来同步对象,因此引用myObject的任何其他代码都可以执行任何他们喜欢的操作,并且您无法控制它。这是一种非常弱的同步形式。它可以工作,如果代码库中的每个人都理解需要在MyObject上进行同步,但这在实践中很难实现。

答案 1 :(得分:0)

我认为this库是您正在寻找的。特别是StripedKeyLockManagerCountingLock课程可以解决您的问题。您可以在项目中使用库,也可以根据需要调整源代码。 Guava还通过Stripped类提供类似的功能。