Java synchronized的原理解析
开始
类有一个特性叫封装,如果一个类,所有的field都是private的,而且没有任何的method,那么这个类就像是四面围墙+天罗地网,没有门。看起来就是一个封闭的箱子,外面的进不来,里面的出不去,一般来说,这样的类是没用的。
1. 给一个代码块上锁
synchronized(obj){
// some code...
}
这个用法就是使用了obj的锁,来锁定一个代码块。
publicsynchronizedvoid aMethod(){
// some code...
}
这个时候它使用的是当前实例this的锁,相当于下面的模式:
publicvoid aMethod(){
synchronized(this){
// some code...
}
}
2. 两个代码块的互斥
class SyncData {
public void do1() {
synchronized(this) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do1-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void do2() {
synchronized(this) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do2-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
创建1个SyncData的实例,开启2个线程,一个线程调用实例的do1方法,另一个线程调用实例的do2方法,你会看到他们之间是互斥的——即使2个线程访问的是实例的不同的方法,依然不能同时访问。因为决定是否可以同时访问的不再是门,而是锁。只要使用的是相同的对象锁,就会互斥访问。
3. 锁的识别
class SyncData {
private Object lock = new byte[0];
public void do1() {
synchronized(lock) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do1-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
思考下面的代码是否能起到互斥访问的作用:
class SyncData {
public void do1() {
Object lock = new byte[0];
synchronized(lock) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do1-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
这个是不能起到互斥作用的,因为每一次调用,局部变量lock都是不同的实例。也就是说,synchronized使用的锁总是变化的。所以我们再补充一点:只有使用相同的对象锁,才能互斥访问。所以识别所使用的锁,是很重要的。
class SyncData {
public void do1() {
synchronized(this) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do1-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
创建2个实例,分别交给2个线程中的1个去访问,能互斥吗?
class SyncData {
public void do1() {
synchronized(this.getClass()) {
for (int i=0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + "-do1-" + i);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
可以互斥,不管一个类有多少个实例,它们调用getClass()返回的结果都是同一个实例。
总结
- 任何对象实例都有一把内部锁,只有一把。
- 相同的对象锁是互斥访问的充要条件。
- 一个类的实例,可能被多个线程并发访问,才考虑同步控制。
- 在1的前提下,只有会导致数据状态出现一段时间的不一致,相关的代码片段才需要同步控制。
- 在2的前提下,只有两块代码会相互干扰时,才必须使用同一把对象锁,来实现互斥;如果相互之间没有影响,建议使用不同的对象锁,以保持并发性能。
- 在不能确认数据状态是否会不一致的情况下,按照会不一致的情况考虑
- 在不能确认两块代码是否有干扰的情况下,按照会有干扰的情况考虑
参考
- Java中Synchronized的用法
介绍了使用synchronized的几种方式,以及相互的区别,写的很好,建议也看一下,相互印证。
Java synchronized的原理解析的更多相关文章
- java线程池原理解析
五一假期大雄看了一本<java并发编程艺术>,了解了线程池的基本工作流程,竟然发现线程池工作原理和互联网公司运作模式十分相似. 线程池处理流程 原理解析 互联网公司与线程池的关系 这里用一 ...
- 【Java并发编程】24、Synchronized实现原理解析
一.概述 我们知道在JDK1.5之前synchronized是一个重量级锁,相对于j.u.c.Lock,它会显得那么笨重,以至于我们认为它不是那么的高效而慢慢摒弃它. 不过,随着后续Java版本更新对 ...
- Java Synchronized的原理
我们先通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的: public class SynchronizedDemo{ public void method(){ syn ...
- Java synchronized实现原理总结和偏量锁、轻量锁、重量锁、自旋锁
synchronized实现同步的基础:Java中的每一个对象都可以作为锁.具体表现为以下3种形式. 对于普通同步方法,锁是当前实例对象(this). 对于静态同步方法,锁是当前类的Class对象. ...
- java synchronized 的原理。
synchronized的作用大概分为三种: 1.确保多线程互斥的访问多线程代码.2.保证变量的可见性.3.防止指令重排序. 那么synchronized 是如何实现这些功能的. public cla ...
- java synchronized 关键字原理
Synchronized 关键字是解决并发问题常用解决方案,有以下三种使用方式: 同步普通方法,锁的是当前对象.同步静态方法,锁的是当前 Class 对象.同步块,锁的是 {} 中的对象. 实现原理: ...
- Java反序列化漏洞原理解析(案例未完善后续补充)
序列化与反序列化 序列化用途:方便于对象在网络中的传输和存储 java的反序列化 序列化就是将对象转换为流,利于储存和传输的格式 反序列化与序列化相反,将流转换为对象 例如:json序列化.XML序列 ...
- Java并发之synchronized关键字深度解析(二)
前言 本文继续[Java并发之synchronized关键字深度解析(一)]一文而来,着重介绍synchronized几种锁的特性. 一.对象头结构及锁状态标识 synchronized关键字是如何实 ...
- Java并发包JUC核心原理解析
CS-LogN思维导图:记录CS基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN JUC 分类 线程管理 线程池相关类 Executor.Executor ...
随机推荐
- 原生JS实现点击一个按钮显示一个div,再点击按钮div隐藏,或点击除div外其它空白处div隐藏
<!DOCTYPE html> <html style="font-size: 24px"> <head> <title>js点击按 ...
- LightOJ 1166 Old Sorting 置换群 或 贪心 水题
LINK 题意:给出1~n数字的排列,求变为递增有序的最小交换次数 思路:水题.数据给的很小怎么搞都可以.由于坐标和数字都是1~n,所以我使用置换群求循环节个数和长度的方法. /** @Date : ...
- PAT 1009. Triple Inversions (35) 数状数组
Given a list of N integers A1, A2, A3,...AN, there's a famous problem to count the number of inversi ...
- 【CODEVS】1033 蚯蚓的游戏问题
[算法]网络流-最小费用最大流(费用流) [题解]与方格取数2类似 在S后添加辅助点S_,限流k 每条边不能重复走,限流1 #include<cstdio> #include<alg ...
- Broken Necklace
Description 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个 例子: 1 2 1 2 r b b r b ...
- Linux增加swap文件
起因 在阿里云搞了台ECS,但是内存就1个G,操作总是悲剧的卡卡卡,于是就想着增加一点交换文件来缓解一下. 快速添加交换文件 step 1. 生成文件 先填充一个大文件,等会儿当做交换文件用: dd ...
- U盘出现大量乱码文件,并且不能彻底删除
问题如图所示: 问题出现原因:不正常的插拔等情况造成的,导致U盘的文件分配表错乱了 解决方法:参考http://bbs.cfanclub.net/thread-405004-1-1.html 运行ch ...
- 阿里云一键web环境包
下载地址:https://files.cnblogs.com/files/wordblog/af3a48ef-3a13-479e-85c9-ead61173126c.zip 先把安装包传到服务器上用w ...
- 第5堂音频课:发音&词串&自学方法示范
1. 发音怎么练习 我讲解的第5-6节发音课,就像一个有用教练,教你的划水姿势,你学了以后,在床上趴着练练蹬腿,然后,要立刻跳下水去游泳,也就是说,你要去听英语: 请你听一段可可宝贝APP的绘本故事, ...
- 一. Jmeter--使用代理录制脚本
Jmeter脚本是以.JMX格式为主 1. Jmeter也是支持录制的,支持第三方录制方式和代理录制方式. (1).第三方录制主要是通过badboy来录制,录制后另存为jmx格式即可. (2).Jme ...