繁体   English   中英

我是否必须将类扩展到 ConcurrentHashMap 或者我可以为 threadSafety 使用变量 ConcurrentHashMap

[英]Do I have to extend class to ConcurrentHashMap or can I have variable ConcurrentHashMap for threadSafety

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

我有两个想法,但我不确定第一个是否可行,所以第一个将创建仅实现 Serializable 的类,该类具有可变日期,然后是线程想要操作的变量 ConcurrentHashMap,第二个想法是拥有扩展 Concurrent 的类哈希映射,只是 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的构造Localdate完成对象的初始化,对象本身就会跨线程可见。 但是当它被赋值给不同对象中的引用变量时,这个赋值(即引用变量的内容)是否对其他线程可见是我们需要注意的。

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

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

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

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

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

基本上,这两种方法是等效的。 从架构的角度来看,在专用类中创建变量是首选,因为可以更好地控制用户可以访问哪些方法。 在扩展时,用户可以访问底层 ConcurrentHashMap 的许多方法并滥用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM