gpt4 book ai didi

java - 我必须将类扩展到 ConcurrentHashMap 还是我可以为 threadSafety 使用变量 ConcurrentHashMap

转载 作者:行者123 更新时间:2023-11-30 10:07:52 25 4
gpt4 key购买 nike

我正在创建基于 Socket 的服务器-客户端预订服务,并且遇到有关将由多个线程访问的类的问题,是否需要扩展 ConcurrentHashMap 或创建变量 ConcurrentHashMap 是否足以保证线程安全?

我有两个想法,但我不确定第一个是否可行,所以第一个是创建仅实现 Serializable 的类具有可变日期,然后是变量 ConcurrentHashMap,线程要在其上运行,第二个想法是创建类它扩展了 Concurrent Hash Map 并且只是 CHP,但具有附加变量以确保它与其他变量区分开来

public class Day implements Serializable {
private LocalDate date;
private ConcurrentHashMap<String, Boolean> schedule;

public Day(LocalDate date){
this.date = date;
this.schedule = new ConcurrentHashMap<>();
IntStream.range(10, 18).forEachOrdered(
n -> this.schedule.put(LocalTime.of(n, 0).toString(), TRUE));
}

public void changeaval(String key,Boolean status) {
this.schedule.replace(key,status);
}

public boolean aval(String key){
return this.schedule.get(key);
}

public LocalDate getDate(){return this.date;}

public ConcurrentHashMap getSchedule(){return this.schedule;}

}

我只想拥有可以被多个线程访问的类/对象,并且可以与其他/可比较的区别开来,并且具有映射 Int -> Boolean 的 ConcurrentHashMap这是我第一次使用 Stack,这是我在 Java 中的第一个项目,所以如果有什么地方不对,我不知道很抱歉。

最佳答案

在处理多线程访问的对象时,基本上需要注意两件事:

  1. 竞争条件 - 由于操作系统的线程调度和编译器的指令重新排序优化,指令以程序员不希望的顺序执行,从而导致错误
  2. 内存可见性 - 在多处理器系统中,一个处理器所做的更改并不总是立即对其他处理器可见。出于性能原因,处理器将内容保存在其本地寄存器和缓存中,因此对其他处理器正在执行的线程不可见。

幸运的是,我们可以使用适当的同步处理这两种情况。

让我们谈谈这个特定的程序。

Localdate 本身是一个不可变的线程安全类。如果我们查看此类的源代码,我们会发现此类的所有字段都是 final。这意味着一旦 Localdate 的构造函数完成对象的初始化,对象本身就会跨线程可见。但是当它被赋值给另一个对象中的引用变量时,这个赋值(也就是引用变量的内容)是否对其他线程可见是我们需要注意的。

鉴于您的情况下的构造函数,我们可以确保字段 date 跨线程的可见性 provided datefinal volatile。由于您没有修改类中的 date 字段,因此您可以很好地将其设置为 final 并确保安全初始化。如果您稍后决定为该字段设置一个 setter 方法(取决于您的业务逻辑和设计),您应该将该字段设置为 volatile 而不是 finalvolatile 创建一个happens-before 关系,这意味着在写入 volatile 变量之前在特定线程中执行的任何指令将立即可见其他线程一读取相同的 volatile 变量就发送给其他线程。

同样适用于 ConcurrentHashMap。您应该使字段 schedule final。由于 ConcurrentHashMap 本身包含所有必要的同步,因此当其他线程尝试读取它时,您针对键设置的任何值都将对它们可见。

但是请注意,如果您有一些可变对象作为 ConcurrentHashMap 值而不是 Boolean,则必须按照上述相同的方式设计它。

另外,知道有一个叫做 piggy-backing 的概念可能会很好,这意味着如果一个线程写入它的所有字段,然后写入一个volatile 变量,线程在写入 volatile 变量之前写入的所有内容对其他线程都是可见的,前提是其他线程首先读取 volatile 变量的值由第一个线程编写。但是当你这样做的时候,你必须非常小心地确保读写的顺序,而且很容易出错。所以,当你想从一段罕见的代码中挤出最后一滴性能时,就可以这样做。在性能之前优先考虑安全性、可维护性和可读性。

最后,代码中没有竞争条件。唯一发生的写入是在 ConcurrentHashMap 上,它本身是线程安全的。

关于java - 我必须将类扩展到 ConcurrentHashMap 还是我可以为 threadSafety 使用变量 ConcurrentHashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54057865/

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