gpt4 book ai didi

java - 复合编辑的并发性

转载 作者:行者123 更新时间:2023-12-04 07:00:23 24 4
gpt4 key购买 nike

我有这些类用于创建我想在运行时存储的对象

Class Person
String name
Pet[] pets

Class Pet
String name
Person[] owners
boolean neutered

起初我使用这些 HashMaps 来存储它们
HashMap people
HashMap pets

但我想让实现并发,所以我像这样改变了这些 map
ConcurrentHashMap people
ConcurrentHashMap pets

我用了 "compareAndSet in a while loop" pattern进行原子更新。

但是我还是有问题,因为我的 People中的每个人 map 在 Pets中关联了宠物 map 。为了保持更新的原子性,我添加了 ReentrantReadWriteLocks这样我就可以更新 People对象同时与关联 Pet对象。
ConcurrentHashMap people
ConcurrentHashMap peopleLocks
ConcurrentHashMap pets
ConcurrentHashMap petLocks

现在,当我对多条记录执行编辑时,我首先获取所有写锁,然后进行编辑,最后释放写锁。这确保在我进行更新时没有阅读。
changePetNames(Person person, Pets[] pets, String[] names) {
// get Person lock
// get Pet locks
// make updates
// release locks
}

neuter(Pets[] pets) {
// get Pet locks
// make updates
// release locks

然后我让我所有的编辑方法在一个对象上同步,这样竞争编辑就不会死锁
private final Object leash = new Object();
changePetNames(Person person, Pets[] pets, String[] names) {
synchronized(leash) {
// get Person lock
// get Pet locks
// make updates
// release locks
}
}

neuter(Pets[] pets) {
synchronized(leash) {
// get Pet locks
// make updates
// release locks
}
}

所以现在我有了允许并发读取和同步写入的运行时存储。我的问题是是否有一种方法可以在保护人与宠物之间的关系的同时使写入并发。

最佳答案

您可以在 People 上同步,而不是在 leash 对象上进行同步。人对象。这允许对不同的人和他们的宠物进行并发更改,同时阻止对一个人和她的宠物进行同时更改。

PS,从外观上看,您的锁定系统似乎有点过于复杂。假设 People - Pets 是一对多的关系,一个人可以有很多宠物,但任何宠物只有一个主人,只有在 person 对象上同步可能就是你所需要的。

PS2,命名很重要,你的类名是复数,我想使用PersonPet而不是 PeoplePets将更好地描述概念,使您的代码更容易理解。

编辑
方法如 neuter只需要宠物而不需要更改所有者中的数据,为了使它们并发,在宠物上同步,但这意味着:

  • 编辑人物和她的宠物时,需要同步人物和宠物,防止宠物只变化
  • 有时宠物可以上锁,而养宠物的人也需要上锁

  • 当一个线程拥有宠物锁并尝试获取人员锁而另一个线程拥有人员锁并尝试获取宠物锁时,上述情况会导致死锁情况。我的解决方案是在所有者上同步,即使只需要更改宠物,这意味着 changePetNames 和 neuter 将如下所示:
    changePetNames(Person person, Pets[] pets, String[] names) {
    synchronized(person) {
    // make updates
    }
    }

    neuter(Pets[] pets) {
    for (Pets pet: pets) {
    // make sure pets owner exists
    synchronized(pet.getOwner()) {
    // make updates
    }
    }
    }

    这样,如果您从不在不同的人上嵌套同步操作,就不会发生死锁。

    编辑 2
    当主人与宠物是多对多关系时,您需要同步一个独特的人和宠物组合的表示,这将重现您已经为更新而获得的写锁。我的结论是,如果您可以确保不会发生死锁,则不需要额外的同步租用。

    如果两个线程想要获取另一个之前已经获取过的锁,就会发生死锁,所以如果你能确保总是以相同的顺序获取锁,这个问题就不会发生。

    如果您向 Person 和 Pet 都添加唯一的创建 ID 并始终按递增顺序获取每个更新集的锁,则不会发生死锁情况:
    changePetNames(Person person, Pets[] pets, String[] names) {
    // sort Person ID's
    // get Person lock in ID sequence
    // sort Pet ID's
    // get Pet locks in ID sequence
    // make updates
    // release locks
    }

    应该做的伎俩。

    关于java - 复合编辑的并发性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1966293/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com