java 中的 volatile AND synchronized
要了解 Java中的 volatile 首席要从线程间通讯开始
概念:
- 对于声明了 volatile 的变量进行写的操作时, JVM 会向处理器(CPU) 发送一条 Lock 前缀的指令, 会将这个变量所在缓存行的数据写回到系统内存(
主内存
) - 在多处理器的情况下, 保持各个处理器缓存一致性的特点, 就会实现缓存一致性协议
- 但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。
- 每个处理器通过嗅探在主内存上传播的数据来检查自己缓存的值是不是过期了
- 当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,就会重新从系统内存中把数据读到处理器缓存里。
- 总之 volatile 做的事情是: 在多线程执行中保证共享对象的一致性
synchronized
public class Demo { private static int i = 0; public static void main(String[] args) { synchronized(Demo.class) { i++; } } }
javap -c -v Demo.class : 结果
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2 // class Demo 2: dup 3: astore_1 4: monitorenter 5: getstatic #3 // Field i:I 8: iconst_1 9: iadd 10: putstatic #3 // Field i:I 13: aload_1 14: monitorexit 15: goto 23 18: astore_2 19: aload_1 20: monitorexit 21: aload_2 22: athrow 23: return Exception table: from to target type 5 15 18 any 18 21 18 any LineNumberTable: line 6: 0 line 7: 5 line 8: 13 line 9: 23 StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 18 locals = [ class "[Ljava/lang/String;", class java/lang/Object ] stack = [ class java/lang/Throwable ] frame_type = 250 /* chop */ offset_delta = 4
monitorenter : 进入并获取对象监视器 monitorexit : 释放并退出对象监视器
- synchronized获得并释放监视器, 如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行。
- volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。
- 显然synchronized要比volatile消耗更多资源。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
PostgreSQL 10.1 手册_部分 III. 服务器管理_第 17 章 在Windows上从源代码安装
第17章在Windows上从源代码安装 目录 17.1. 使用Visual C++或Microsoft Windows SDK构建 17.1.1. 要求 17.1.2. 针对64位Windows的特殊考虑 17.1.3. 构建 17.1.4. 清理和安装 17.1.5. 运行回归测试 17.1.6. 构建文档 对于大部分用户,推荐下载Windows的二进制发布,它在PostgreSQL的网站上作为一个图形化安装包可供下载。从源代码构建的方式只适合于希望开发或者扩展PostgreSQL的人们。 有多种不同的方式可以在Windows上构建PostgreSQL。 用微软工具进行构建的最简单方式是安装Visual Studio Express 2017 for Windows Desktop并使用其中包含的编译器。 也可以使用完整的Microsoft Visual C++ 2005到2017来构建。 在某些情况中除了编译器还需要安装Windows SDK。 也可以使用由MinGW提供的GNU编译器工具来构建PostgreSQL,或者使用适合于旧版本Windows的Cygwin。 使用MinGW...
- 下一篇
leetcode算法题学习Java版(2)
283.Move Zeros(移动零) 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。 class Solution { public void moveZeroes(int[] nums) { int k = 0; for(int i = 0;i<nums.length;i++){ if(nums[i]!=0){ if(i!=k){ int temp = nums[k]; nums[k] = nums[i]; nums[i] = temp; } k++; } } } } 75.Sort Colors(颜色分类) 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地**对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 注意: 不能使用代码库中的排序函数来解决这道题。 示例:输入: [2,0,2...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8安装Docker,最新的服务器搭配容器使用