如何在线程之间共享资源?

640?wx_fmt=png

点击“蓝字”关注Java高级部落!


介绍


当涉及IO读/写时,多线程可以提高应用程序性能。不幸的是,共享资源(共享变量)在每个CPU缓存中可以有不同的版本。结果是应用程序的行为无法预测。Java提供了synchronized关键字,以便在CPU的缓存中保持共享资源的一致性。不幸的是,synchronized关键字会降低应用程序的速度。

640?wx_fmt=jpeg

我使用JMH作为AverageTime模式的微基准,它意味着基准测试的结果是每个测试用例的平均运行时间,更低的输出更好。您可以在此链接中找到有关微基准的更多信息。


为什么同步减速应用程序?


当线程被锁定并开始执行同步块中的指令时,所有其他线程将被阻塞并变为空闲。将存储这些线程的执行上下文(CPU缓存,指令集,堆栈指针...),并且将恢复其他活动线程的执行上下文以恢复计算。它被称为上下文切换,需要系统的大量工作。任务调度程序还必须运行以选择将加载哪个线程。


volatile关键字


volatile关键字只是做了一些事情:告诉CPU从主内存读取资源的值,而不是CPU的缓存; 在每次后续读取该字段之前发生对易失性字段的写入。 易失性永远不会比同步具有更高volatile的开销,synchronized如果synchronized块只有一个操作,则具有相同的开销。

640?wx_fmt=jpeg

volatile如果只有一个写线程,关键字效果很好。如果有2个或更多写入线程,将发生竞争条件:所有写入线程获取最新版本的变量,在其自己的CPU上修改值,然后写入主存储器。结果是内存中的数据只是一个线程的输出,其他线程的修改被覆盖。


包java.util.concurrent


Doug Lea在创建和改进这个软件包时做了很棒的工作。这个包有很多用于管理线程的工具,还包含一些线程安全的数据结构。这些数据结构也在使用synchronizedvolatile引导下,但是以复杂的方式,您可以获得比编写自己的代码更好的性能。


ConcurrentHashMap“遵循与”相同的功能规范Hashtable“,并为您提供线程安全的优势。

640?wx_fmt=jpeg

AtomicInteger和其他类似的类使用volatileUnsafe.compareAndSwapInt。AtomicInteger可以调用忙等待,这意味着线程总是检查条件执行。此线程什么也不做,但任务调度程序无法检测到此检查并认为此线程正忙,因此任务调度程序无法将CPU带到另一个准备执行的线程。如果条件可以在几个CPU时钟之后存档,那么繁忙等待很有效。我们可以在基准测试结果中看到同步不稳定。

640?wx_fmt=jpeg



Lock具有比synchronized您更灵活的功能,您可以使用tryLock()特定时间等待,或者可以确保最长等待线程获得具有公平性选项的锁定。但synchronized关键字可以保证执行顺序和数据新鲜度,源代码synchronized也很简单。Lock将是一个噩梦,如果一个初级开发者忘记调用unlock()或不投入unlock()的finally块。

640?wx_fmt=jpeg

我使用不同数量的线程进行基准测试:从2个线程到64个线程。我们可以看到同步工作比具有2个线程的ReentrantLock好得多,但在具有64个线程的情况下,ReentrantLock具有更好的性能。


不可变对象


这个想法很简单,如果一个对象永远不会改变值,那么它是线程安全的。但是存在一个问题,每次要更改某些值时都必须创建一个新对象,因此GC过热。有些库可以使不可变对象更容易处理,比如https://immutables.github.io


结论


使用synchronized关键字可以轻松地在线程之间共享资源,但它可能导致全世界的等待并使您的应用程序变慢。其他简单的技术也可以存档线程安全,但速度快synchronized


看到这里,你想不想踩在过来人的肩膀上,轻松实现专业技能的提升呢?不妨扫码加入java技术交流分享群,体验精彩公开课,还能免费领取更多学习资料。

640?wx_fmt=png

添加「java技术交流分享群」,开启你的技能提升之旅吧~


640?wx_fmt=jpeg

点击下方“阅读原文

添加「java技术交流分享群查看更多~

↓↓↓ 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值