如何在线程之间共享资源?
点击“蓝字”关注Java高级部落!
介绍
当涉及IO读/写时,多线程可以提高应用程序性能。不幸的是,共享资源(共享变量)在每个CPU缓存中可以有不同的版本。结果是应用程序的行为无法预测。Java提供了synchronized关键字,以便在CPU的缓存中保持共享资源的一致性。不幸的是,synchronized关键字会降低应用程序的速度。
我使用JMH作为AverageTime模式的微基准,它意味着基准测试的结果是每个测试用例的平均运行时间,更低的输出更好。您可以在此链接中找到有关微基准的更多信息。
为什么同步减速应用程序?
当线程被锁定并开始执行同步块中的指令时,所有其他线程将被阻塞并变为空闲。将存储这些线程的执行上下文(CPU缓存,指令集,堆栈指针...),并且将恢复其他活动线程的执行上下文以恢复计算。它被称为上下文切换,需要系统的大量工作。任务调度程序还必须运行以选择将加载哪个线程。
volatile关键字
volatile关键字只是做了一些事情:告诉CPU从主内存读取资源的值,而不是CPU的缓存; 在每次后续读取该字段之前发生对易失性字段的写入。 易失性永远不会比同步具有更高volatile的开销,synchronized如果synchronized块只有一个操作,则具有相同的开销。
volatile如果只有一个写线程,关键字效果很好。如果有2个或更多写入线程,将发生竞争条件:所有写入线程获取最新版本的变量,在其自己的CPU上修改值,然后写入主存储器。结果是内存中的数据只是一个线程的输出,其他线程的修改被覆盖。
包java.util.concurrent
Doug Lea在创建和改进这个软件包时做了很棒的工作。这个包有很多用于管理线程的工具,还包含一些线程安全的数据结构。这些数据结构也在使用synchronized和volatile引导下,但是以复杂的方式,您可以获得比编写自己的代码更好的性能。
ConcurrentHashMap“遵循与”相同的功能规范Hashtable“,并为您提供线程安全的优势。
AtomicInteger和其他类似的类使用volatile和Unsafe.compareAndSwapInt。AtomicInteger可以调用忙等待,这意味着线程总是检查条件执行。此线程什么也不做,但任务调度程序无法检测到此检查并认为此线程正忙,因此任务调度程序无法将CPU带到另一个准备执行的线程。如果条件可以在几个CPU时钟之后存档,那么繁忙等待很有效。我们可以在基准测试结果中看到同步不稳定。
锁
Lock具有比synchronized您更灵活的功能,您可以使用tryLock()特定时间等待,或者可以确保最长等待线程获得具有公平性选项的锁定。但synchronized关键字可以保证执行顺序和数据新鲜度,源代码synchronized也很简单。Lock将是一个噩梦,如果一个初级开发者忘记调用unlock()或不投入unlock()的finally块。
我使用不同数量的线程进行基准测试:从2个线程到64个线程。我们可以看到同步工作比具有2个线程的ReentrantLock好得多,但在具有64个线程的情况下,ReentrantLock具有更好的性能。
不可变对象
这个想法很简单,如果一个对象永远不会改变值,那么它是线程安全的。但是存在一个问题,每次要更改某些值时都必须创建一个新对象,因此GC过热。有些库可以使不可变对象更容易处理,比如https://immutables.github.io。
结论
使用synchronized关键字可以轻松地在线程之间共享资源,但它可能导致全世界的等待并使您的应用程序变慢。其他简单的技术也可以存档线程安全,但速度快synchronized。
看到这里,你想不想踩在过来人的肩膀上,轻松实现专业技能的提升呢?不妨扫码加入java技术交流分享群,体验精彩公开课,还能免费领取更多学习资料。
添加「java技术交流分享群」,开启你的技能提升之旅吧~
点击下方“阅读原文”
添加「java技术交流分享群」查看更多~
↓↓↓
如何在线程之间共享资源?相关推荐
- python线程的注意点(线程之间执行是无序的、主线程会等待所有的子线程执行结束再结束(守护主线程)、线程之间共享全局变量、线程之间共享全局变量数据出现错误问题(线程等待(join)、互斥锁))
1. 线程的注意点介绍 线程之间执行是无序的 主线程会等待所有的子线程执行结束再结束 线程之间共享全局变量 线程之间共享全局变量数据出现错误问题 2. 线程之间执行是无序的 import thread ...
- Java高并发编程:多个线程之间共享数据的方式探讨
内容摘要 多个线程之间共享数据,按照每个线程执行代码是否相同,我们可以采取不同的处理方式,这里通过简单的卖票示例说明了当每个线程执行相同代码的情况,对于多个线程执行不同代码的情况,处理方式比较灵活,这 ...
- android4.4 fragment,在Activity和多个Fragment之间共享资源
在Activity和多个Fragment之间共享资源 Android Studio 默认生成的代码一般是这样的: package com.messy.lingplayer.playui import ...
- 如何在两个线程之间共享数据
两个线程之间共享数据的方式 Java 里面进行多线程通信的主要方式就是共享内存的方式,共享内存主要的关注点有两个:可见 性和有序性原子性.Java 内存模型(JMM)解决了可见性和有序性的问题,而锁解 ...
- 线程的共享资源与独立资源
进程拥有两个基本的属性: 资源的拥有者和独立调度单位. 进程是资源分配和独立运行的基本单位,每一个进程都完成一个特定的任务. 线程的引入进一步提高了程序并发执行的程度,从而进一步提高了资源的利用率和系 ...
- 同一进程中线程的共享资源以及独占资源
线程之间的共享资源以及独占资源 共享资源 独占资源 共享资源 1.进程申请的堆内存 2.进程打开的文件描述符 3.进程的全局数据(可用于线程之间通信) 4.进程ID.进程组ID 5.进程目录 6.信号 ...
- 线程的创建 验证线程之间共享数据 守护线程 线程进程效率对比 锁 死锁 递归锁...
线程(from threading import Thread):CPU调度的最小单位 线程的两种创建方式:方式一: 1 from threading import Thread 2 def f1(i ...
- java 多线程 共享数据_JAVA多线程提高四:多个线程之间共享数据的方式
多个线程访问共享对象和数据的方式 如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 如果每个线程执行的代码不同,这 ...
- Java多线程多个线程之间共享数据
线程范围的共享变量 多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象 public class ThreadScopeSharaData {priva ...
最新文章
- _fseeki64在linux下的头文件,fseek能处理2GB以上的文件吗?
- Linux 搜索指令
- 160个Crackme035
- Win10环境下,word2016嵌入mathtype出现灰色的解决办法
- bean注入属性_摆脱困境:将属性值注入配置Bean
- 前端学习(1797):前端调试之html/css介绍
- 如何使用域组策略(AD GPO)分发软件安装以及卸载[1.31.2013更新]
- 最简单的基于时间片轮转任务调度模型
- 如何调节电脑显示屏来保护双眼的小技巧
- “Mom, isn‘t Su Ruoxia coming back today?
- 嵌入式系统是云服务器,一步步教你使用云端服务器yeelink远程监控
- Jenkins持续集成案例之-运维部署方式
- poj 1269 Intersecting Lines
- ffmpeg 使用小记
- FlappyBird(像素鸟)小游戏 (基于 LabVIEW 保姆级教程)
- 酷派7269_酷派7269(联通版)救砖教程 线刷教程 图文详解 附线刷工具下载
- Python制作含微软雅黑字体的图片报错,中文字体报错可用类似方式处理
- 无人机三维建模(1) 调研
- 关系型、非关系型、实时、非实时数据库特点归纳
- 机器学习中的独立同分布(I.I.D.)假设
热门文章
- 搭建室外四轴无人机(一)
- java lombok.getter_详解lombok @Getter @Setter 使用注意事项
- 去掉office2003盗版五角星的办法(组图)
- 黑客你咋这么牛掰,不屑用鼠标?
- 第十章 初识面向对象
- 简单的方法Android的数据恢复你的Andr​​oid手机
- 渗透测试国内外研究_浅析晶硅光伏背板阻隔性能测试(一)——水蒸气透过率测试...
- iOS H5 获取麦克风权限
- 货币兑换java程序,货币兑换API Java GUI
- [RK3288][Android6.0] PWM backlight 驱动流程小结