2 回答
![?](http://img1.sycdn.imooc.com/54584f9d0001219b02200220-100-100.jpg)
TA贡献1804条经验 获得超8个赞
处理多个线程访问的对象时,基本上需要注意两件事:
竞争条件-由于操作系统进行了线程调度并且编译器对指令进行了重新排序优化,因此指令的执行顺序不符合程序员的预期,从而导致错误
内存可见性-在多处理器系统中,一个处理器所做的更改并不总是立即对其他处理器可见。处理器出于性能原因将内容保留在其本地寄存器和缓存中,因此对于其他处理器正在执行的线程不可见。
幸运的是,我们可以使用适当的同步来处理这两种情况。
让我们来谈谈这个特定的程序。
Localdate
本身就是一个不变且线程安全的类。如果我们查看此类的源代码,则会看到此类的所有字段均为final
。这意味着,一旦final的构造函数Localdate
完成了对象的初始化,就可以在线程之间看到对象本身。但是,当将其分配给不同对象中的参考变量时,我们需要关注的是分配(换句话说,参考变量的内容)是否对其他线程可见。
鉴于你的情况的构造,我们可以确保该领域的知名度date
跨线程提供 date
要么final
或volatile
。由于您没有date
在类中修改字段,因此可以很好地使其成为最终字段,从而确保安全的初始化。如果您以后决定对此字段使用setter方法(取决于您的业务逻辑和设计),则应将其设置为volatile
而不是final
。volatile
创建一个事前发生关系,这意味着volatile
在其他线程中读取任何易失变量后,在写入该变量之前在该特定线程中执行的任何指令将立即对其他线程可见。
同样适用ConcurrentHashMap
。你应该做的领域schedule
final
。由于ConcurrentHashMap
它本身具有所有必要的同步,因此您在其他密钥尝试读取密钥时,对密钥设置的任何值将对其他线程可见。
但是请注意,如果您使用一些可变对象ConcurrentHashMap
代替值Boolean
,则必须采用与上述相同的方法进行设计。
另外,最好知道有一个称为“背负式备份”的概念,这意味着,如果一个线程写入其所有字段,然后写入volatile
变量,则线程在写入该volatile
变量之前写入的所有内容对于该线程都是可见的。其他线程,前提是其他线程volatile
在第一个线程写入变量后首先读取该变量的值。但是,当您执行此操作时,必须非常仔细地确保读和写的顺序,并且容易出错。因此,当您想从一段罕见的代码中挤出最后的性能下降时,就可以这样做。在性能之前优先考虑安全性,可维护性和可读性。
最后,代码中没有竞争条件。唯一正在发生的写操作ConcurrentHashMap
本身就是线程安全的。
![?](http://img1.sycdn.imooc.com/533e4d510001c2ad02000200-100-100.jpg)
TA贡献1811条经验 获得超6个赞
基本上,这两种方法是等效的。从体系结构的角度来看,最好在专用类中创建一个变量,因为它可以更好地控制用户可以访问哪些方法。扩展时,用户可以访问基础ConcurrentHashMap的许多方法并滥用它们。
添加回答
举报