使用UUID作为密钥时映射的线程安全性



有一个服务包含一个final字段。

@Service
public class RegularService {
private final DataMap map = new DataMap();
....
}

这个final字段有一个类DataMap,看起来像这个

class DataMap {
private Map<UUID, String> content1 = new HashMap<>();
private Map<UUID, String> content2 = new HashMap<>();
void updateContent(UUID id, String data) {
if (content1.containsKey(id)) {
....
return;
}

if (content2.containsKey(id)) {
content1.put(id, data);
content2.remove(id);
return;
}
content2.put(id, data);
}

问题是,updateContent是否具有竞赛条件?问题是,理论上使用UUID意味着不同的线程永远不会访问相同的条目。。。

如果是,那么是否需要同步整个updateContent方法,或者仅使用ConcurrentHashMap就足够了?

问题是,在理论上使用UUID意味着不同的线程永远不会访问相同的条目。。。

这根本不是真的。这并不能保证。你是怎么得出这个结论的?我很想知道。

如果是,那么是否需要同步整个updateContent方法,或者只使用ConcurrentHashMap就足够了?

您不必同步整个函数,只需同步修改映射的位即可。您可以使用ConcurrentHashMap来解决此问题,但这会对性能造成重大影响。

使用UUID作为密钥时映射的线程安全性

映射的线程安全性实际上与所讨论的关键对象无关。仅仅因为UUID.randomUUID()返回一个唯一的UUID并不能以某种方式保证线程安全。问题在于内存同步,以及线程将如何查看和发布对映射的更改以及协调多个映射操作。

问题是updateContent()是否具有竞争条件?

是的。首先,如果不使用同步或并发的Map实现,就无法使用多个线程更新MapConcurrentHashMap将负责对映射的修改和线程之间内存的发布,以保持它们的同步。但是,由于您正在对需要协调的映射进行多个操作,因此需要添加更多的同步。

如果是,那么是否需要同步整个updateContent()方法,或者只使用ConcurrentHashMap就足够了?

由于要对2个映射进行多次更改,因此需要使用synchronized或以其他方式锁定多个操作。一旦做到了这一点,就没有必要使用ConcurrentHashMap。您可以使方法synchronized锁定其中一个映射,也可以使特定的final Object lockObject = new Object()用于锁定操作。

例如,在没有锁的情况下,没有任何东西可以保护线程1查看content1不包含id XXX,然后在线程2将其添加到content1之前继续检查content2。所以thread1会覆盖thread2的data,我想这不是你想要的。

相关内容

  • 没有找到相关文章

最新更新