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 ...
随机推荐
- CCPC2018-A-Buy and Resell
Problem Description The Power Cube is used as a stash of Exotic Power. There are n cities numbered 1 ...
- 还不会做! 树上的gcd 树分治 UOJ33
题目链接:http://uoj.ac/problem/33 题解链接:http://vfleaking.blog.uoj.ac/blog/38 现在感觉到了做OI的层层递进的思路的伟大之处,作为一个大 ...
- 817D. Imbalanced Array 预处理最大最小 思维
LINK 题意:给出n个数,求所有子区间的最大最小值差的和. 思路:过去有道题目是求所有子区间的最大值或最小值,这题类似,我们对每一个数计算其作为最大值得次数和最小值的次数,这两个值求法类似,都是比左 ...
- System Administrator(构造,图论)
System Administrator time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- 更改gradle的java的class文件输出目录的结构
group 'com.thinkvenus.common'version '1.0-SNAPSHOT' apply plugin: 'java' sourceCompatibility = 1.8 r ...
- 生成验证码tp
js里拼接随机数 页面上链接 去掉后缀名
- Docker微容器Alpine Linux
Alpine 操作系统是一个面向安全的轻型 Linux 发行版. 它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功 ...
- 63.UniquePaths II---dp
题目链接 题目大意:与62题类似,只是这个题中间有障碍. 法一:dfs,依旧超时.代码如下: public int uniquePathsWithObstacles(int[][] obstacleG ...
- docker swarm join 报错
[peter@minion ~]$ docker swarm join --token SWMTKN-1-3mj5po3c7o04le7quhkdhz6pm9b8ziv3qe0u7hx0hrgxsna ...
- java版云笔记(八)之关联映射
Mybatis关联映射 通过数据库对象之间的关联关系,反映到到实体对象之间的引用. 加载多个表中的关联数据,封装到我们的实体对象中. 当业务对数据库进行关联查询. 关联 <association ...