java和线程相关的关键字有哪些_Java中有哪些机制来保证线程安全?synchronized关键字和volatile关键字...
想要解决线程安全问题,首先要知道为什么会造成线程不安全?
在单线程中,我们从来没有提到个线程安全问题,线程安全问题是只出现在多线程中的一个问题。因为多线程情况下有共享数据,每个线程都共享这些数据并对这些数据进行修改,当需要修改数据进行写入时,还有线程调度的交叉执行,还有内存模型的原因引起了不安全问题。
要保证线程安全是一件很难的事,一般我们着眼于以下三个方面:
(三个核心)
1.原子性
2.可见性
3.重排序问题
首先来解释一下,什么是原子性,可见性,重排序问题?
原子性,一段不可再分的代码片段,要么全部执行要么都不执行。(一句代码不一定就是原子的,例如a=b,将b从主内存中加载到工作内存,再将b的值赋给a,最后将a保存到主内存中,很明显是三步。)
可见性,所有的数据存在主内存中,每个线程有自己的工作内存,工作时将数据从主内存中加载到工作内存(这样做有利于提高运行效率),这时候,如果本线程将数据做了修改,其他线程及时的看到了,这就叫可见的(但往往本线程已经修改了数据,在其他线程中还是用的是旧的数据,这就发生了错误,就是不安全问题。)
重排序问题,在单线程中我们的都是按照顺序执行的,但是在多线程中,CPU/编译器/JIT会对代码运行顺序进行一定的调整(按照更加合适的方式执行,优化),但是这样就没办法保证结果的正确性,会出错,这就是代码重排序问题。
为了解决这些不安全问题而产生了synchronized和volatile关键字
接下了我们看看synchronized和volatile是如何保证安全性的,以及学会使用方法,来保证我们自己写的代码的线程安全。
1.synchronized
先学习synchronized 的语法:
1)方法修饰符——和其他修饰符的使用类似
2)代码块——作为代码块出现
接下来,谈谈synchronized 是如何保证线程安全的?
synchronized 是通过给对象加锁,保证了原子性和可见性来使线程安全的,
先看给普通方法加锁,
锁是加在在堆里创建的对象上面,当一个线程抢占CPU成功时,检查该对象,发现锁是开的(锁初始状态下是开的状态),就给这个对象加锁,直到方法执行结束(正常/异常),释放锁。在当前线程加锁运行代码的过程中,不一定可以一直抢占CPU,如果自己的时间片用完了或者主动放弃CPU,线程调度到其他线程,而其他线程这时抢占CPU成功了,这时检查该对象(注意:和前面是同一对象,当前对象,this指向的那个对象)发现已经上锁,这时该线程直接放入阻塞队列,只有当这把锁被释放后,才能重新进入就绪队列,重新获得了抢占CPU的机会,每一把锁都有一个对应的阻塞队列。
再看给静态方法加锁,
给静态方法加的锁,是在放类的方法区里,加在类的元对象上面。
synchronized的代码表现:
| 表现 ---------- | 锁的对象 ------- | 何时加锁---- | 何时释放 - |
|修饰普通方法 | this -------------- | 进入方法---- | 退出方法 - |
|修饰静态方法 | 类名.class ----- | 进入方法 — | 退出方法-- |
| 代码块-------- |小括号引用指向 | 进入代码块 | 退出代码块 |
加锁保证了原子性,并在一定程度上保证了可见性。
在加锁时,所有线程会同步当前的数据,在释放锁时,数据又会同步一次,但是在加锁-解锁这个代码运行的过程中,没有保证可见性。
加锁内部的代码可以进行重排序,外部的代码也可以进行重排序,但是内部和外部之间是不相通的不可以交换代码执行顺序。
使用synchronized的缺点:理论上所有的线程安全问题都可以使用synchronized来解决,但是成本非常高。(不断的进行线程调度本身就会花费很多时间,而且,如果每次都是同一线程抢占CPU成功,其他线程就会一直处于阻塞-抢占的过程中)
在使用synchronized关键字时加锁时,要尽量把它放在合适的位置上,如果范围过大,将没有意义,即关注锁的粒度问题,粗粒度,细粒度。
2.volatile
语法:修饰变量
可以保证该变量的可见性问题(不再赘述)
可以部分保证代码的重排序问题(对象初始化,分为三步:new 、 对象初始化、对象赋值给引用。volatile可以保证这三步是顺序执行的)
关于原子性的一个总结:
基本数据类型里,
byte、int、Boolean、float、char、short作为字面量时是原子的,作为变量时不是原子的;
long、double在任何时候都不是原子的。(因为它们都是64位的在32位机运行时,分为低32位和高32位,不是一步执行的)
最后再提一点:单例模型:一个类只会生成一个对象(只有一个实例),大家共用的是同一个实例)
java和线程相关的关键字有哪些_Java中有哪些机制来保证线程安全?synchronized关键字和volatile关键字...相关推荐
- Java多线程学习二十六:原子类是如何利用 CAS 保证线程安全的?
什么是原子类,以及它有什么作用. 在编程领域里,原子性意味着"一组操作要么全都操作成功,要么全都失败,不能只操作成功其中的一部分".而 java.util.concurrent.a ...
- 主线程 唤醒_Java等待唤醒机制统计子线程运行时间的方式及其疑问
我想在主线程中获取子线程运行的时间,一种方式是使用join()方法,经验证是可行的: 但是我想试试等待唤醒机制,思路是:子线程启动后主线程等待,子线程结束后唤醒主线程,但是不太清楚为什么会报错,从运行 ...
- 【Java 并发编程】线程指令重排序问题 ( 指令重排序规范 | volatile 关键字禁止指令重排序 )
文章目录 总结 一.指令重排序规范 二.指令重排序示例 总结 Java 并发的 333 特性 : 原子性 : 每个操作都是 不可拆分的原子操作 ; 在线程中进行 a++ 就不是原子操作 , 该操作分为 ...
- Java并发编程—volatile关键字(保证变量的可见性、有序性机制)
原文作者:Matrix海子 原文地址:Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程 ...
- Java基础——volatile关键字解析
简介 volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来了解一下与内 ...
- Java并发编程:volatile关键字解析(转载)
转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 v ...
- java中volatile_java中volatile关键字的含义
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- 【Java并发编程:volatile关键字之解析】
Java并发编程:volatile关键字解析 - Matrix海子 - 博客园 在Java 5之前,volatile是一个备受争议的关键字:因为在程序中使用它往往会导致出人意料的结果.在Java 5之 ...
- java 传绝对路径无效_【Java并发005】原理层面:volatile关键字全解析
一.前言 在Java 5之前,volatile是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果. 在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽 ...
最新文章
- Android系列讲座(2):为TextView组件加上边框
- linux添加美式键盘,win8\win server 2012添加【中文--美式键盘】
- Discuz学习总结——部分bug解决方案
- 从商业视角理解数据:数据科学家的思维之路
- VISP视觉库识别AprilTag详细解读
- python编程语言能干什么-这 13个,1 行Python代码能干哪些事?
- openfire + spark + sparkweb + pandion 下载地址
- 将mysql的数据库导入到linux_linux 操作之一 如何在linux将本地数据*.sql文件导入到linux 云服务器上的mysql数据库...
- linux安装tf-gpu注意事项
- flutter中state详解
- JVM Attach机制实现
- LQ训练营(C++)学习笔记_常见动态规划模型
- 链接访问后刷新颜色回到初始_如何使链接可访问(提示:颜色不够)
- 2021年中国银发经济洞察报告
- OpenJDK与JDK的区别分析
- webStorm部分以及重要快捷键
- Combinations leetcode 组合问题
- 如何复制或导出托管磁盘
- Netty之Pipeline总结
- 最全java面试题及答案(208道)
热门文章
- 【MySQL】小表驱动大表
- Mac :谷歌浏览器 NET::ERR_CERT_INVALID 此证书已被撤消。网络错误和攻击行为通常是暂时的,因此,此网页稍后可能会恢复正常
- linux句柄过大导致无法登陆
- Flink eventTime案例无输出
- Drools 7.x Rate算法
- WinForm中日期控件开窗
- Java lang3的 StringUtils.isNumeric(str)不能识别负数和小数
- JavaScript模拟call和apply的实现
- [转]SQL中的case when then else end用法
- git安装和GitHub使用