为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

德玛西亚99 2021-03-30 21:16:55
我正在创建基于套接字的服务器-客户端预留服务,并且对将由多个线程访问的类有问题,是否需要扩展ConcurrentHashMap还是足以创建变量ConcurrentHashMap以确保线程安全?我有两个想法,但是我不确定第一个想法是否可以工作,因此第一个想法是创建仅实现Serializable的类,该类具有可变的date,然后创建要在其上操作线程的变量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;}}我只想拥有可以被多个线程访问并且可以与其他线程进行区分/比较的Class / Object,并且具有ConcurrentHashMap,它映射Int-> Boolean这是我第一次使用Stack,这是我在Java中的第一个项目,因此如果有什么不对的地方,我并不后悔
查看完整描述

2 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

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

  1. 竞争条件-由于操作系统进行了线程调度并且编译器对指令进行了重新排序优化,因此指令的执行顺序不符合程序员的预期,从而导致错误

  2. 内存可见性-在多处理器系统中,一个处理器所做的更改并不总是立即对其他处理器可见。处理器出于性能原因将内容保留在其本地寄存器和缓存中,因此对于其他处理器正在执行的线程不可见。

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

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

Localdate本身就是一个不变且线程安全的类。如果我们查看此类的源代码,则会看到此类的所有字段均为final。这意味着,一旦final的构造函数Localdate完成了对象的初始化,就可以在线程之间看到对象本身。但是,当将其分配给不同对象中的参考变量时,我们需要关注的是分配(换句话说,参考变量的内容)是否对其他线程可见。

鉴于你的情况的构造,我们可以确保该领域的知名度date跨线程提供 date要么finalvolatile。由于您没有date在类中修改字段,因此可以很好地使其成为最终字段,从而确保安全的初始化。如果您以后决定对此字段使用setter方法(取决于您的业务逻辑和设计),则应将其设置为volatile而不是finalvolatile创建一个事前发生关系,这意味着volatile在其他线程中读取任何易失变量后,在写入该变量之前在该特定线程中执行的任何指令将立即对其他线程可见。

同样适用ConcurrentHashMap。你应该做的领域schedule final。由于ConcurrentHashMap它本身具有所有必要的同步,因此您在其他密钥尝试读取密钥时,对密钥设置的任何值将对其他线程可见。

但是请注意,如果您使用一些可变对象ConcurrentHashMap代替值Boolean,则必须采用与上述相同的方法进行设计。

另外,最好知道有一个称为“背负式备份”的概念,这意味着,如果一个线程写入其所有字段,然后写入volatile变量,则线程在写入该volatile变量之前写入的所有内容对于该线程都是可见的。其他线程,前提是其他线程volatile在第一个线程写入变量后首先读取该变量的值。但是,当您执行此操作时,必须非常仔细地确保读和写的顺序,并且容易出错。因此,当您想从一段罕见的代码中挤出最后的性能下降时,就可以这样做。在性能之前优先考虑安全性,可维护性和可读性。

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


查看完整回答
反对 回复 2021-04-14
?
杨魅力

TA贡献1811条经验 获得超6个赞

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


查看完整回答
反对 回复 2021-04-14
  • 2 回答
  • 0 关注
  • 133 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信