“规范”的实施锁定对象 [英] Implementation of "canonical" lock objects

查看:113
本文介绍了“规范”的实施锁定对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据对象存储,我希望一次同步与一个特定对象相关的修改。

I have a store of data objects and I wish to synchronize modifications that are related to one particular object at a time.

class DataStore {
    Map<ID, DataObject> objects = // ...
    // other indices and stuff...

    public final void doSomethingToObject(ID id) { /* ...  */ }
    public final void doSomethingElseToObject(ID id) { /* ... */ }
}

也就是说,我不希望我的数据存储具有单个锁,因为对不同数据对象的修改是完全正交的。相反,我希望能够获取仅与单个数据对象相关的锁。

That is to say, I do not wish my data store to have a single lock since modifications to different data objects are completely orthogonal. Instead, I want to be able to take a lock that pertains to a single data object only.

每个数据对象都有唯一的ID。一种方法是创建 ID =>的地图锁定并同步与id关联的一个锁定对象。另一种方法是执行以下操作:

Each data object has a unique id. One way is to create a map of ID => Lock and synchronize upon the one lock object associated with the id. Another way is to do something like:

synchronize(dataObject.getId().toString().intern()) {
    // ...
}

然而,这似乎是内存泄漏 - 可能永远不会收集内化字符串。

However, this seems like a memory leak -- the internalized strings may never be collected.

另一个想法是同步数据对象本身;但是,如果您有一个数据对象尚不存在的操作怎么办?例如,像 addDataObject(DataObject)这样的方法会在什么位置同步?

Yet another idea is to synchronize upon the data object itself; however, what if you have an operation where the data object doesn't exist yet? For example, what will a method like addDataObject(DataObject) synchronize upon?

总结一下,我怎么写函数 f(s),其中 s 字符串,如果 f(s)== f(t)如果 s.equals(t)在内存中-safe方式?

In summary, how can I write a function f(s), where s is a String, such that f(s)==f(t) if s.equals(t) in a memory-safe manner?

推荐答案

对于这种情况,我通常有2级锁定:
作为读者的第一级-writer-lock,确保更新到地图(添加/删除)通过将它们视为写入来正确同步,并且对地图中条目的访问在地图上被视为已读。一旦访问该值,然后同步该值。这是一个小例子:

For such case, I normally have 2 level of lock: First level as a reader-writer-lock, which make sure update to the map (add/delete) is properly synchronized by treating them as "write", and access to entries in map is considered as "read" on the map. Once accessed to the value, then synchronize on the value. Here is a little example:

class DataStore {
    Map<ID, DataObject> objMap = // ...
    ReadWritLock objMapLock = new ReentrantReadWriteLock();
    // other indices and stuff...
    public void addDataObject(DataObject obj) {
        objMapLock.writeLock().lock();
        try {
            // do what u need, u may synchronize on obj too, depends on situation
            objMap.put(obj.getId(), obj);
        } finally {
            objMapLock.writeLock().unlock();
        }
    }

    public final void doSomethingToObject(ID id) { 
        objMapLock.readLock().lock();
        try {
            DataObject dataObj = this.objMap.get(id);
            synchronized(dataObj) {
                // do what u need
            }
        } finally {
            objMapLock.readLock().unlock();
        }

    }
}

一切都应该然后在不牺牲太多并发性的情况下正确同步

Everything should then be properly synchronized without sacrificing much concurrency

这篇关于“规范”的实施锁定对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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