Java并发编程的艺术(三)——synchronized
什么是synchronized
synchronized可以保证某个代码块或者方法被一个线程占有,保证了一个线程的可先性。java 1.6之前是重量级锁,在1.6进行了各种优化,就不那么重了,并引入了偏向锁和轻量级锁,以及锁的存储结构和升级过程。
synchronized实现方式
Java中每个对象都可以作为锁:
- 对于普通同步方法,锁是实例对象。
- 对于静态通同步方法,锁是当前类的Class对象。
- 对于同步方法块,锁是Synchronized括号里的配置对象。
synchronized实现原理
synchronized可以保证方法或者代码块在运行时,同一个时刻只有一个线程可以进入到临界区,同时它还可以保证共享变量的可见性。
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。通过monitorenter和monitorexit指令实现。前者是编译后插入到同步代码块开始的位置,后者是插入到方法结束和异常处。JVM保证每个monitorenter和monitorexit指令是配对的,任何对象都会有一个monitor与之关联,当对对象的monitor被持有后,它就是处于锁定状态。线程执行到monitorenter时,就会尝试获取对象monitor的所有权,就是获取对象锁。
sychronized 特点
- 不能被继承,但是可以调用父类的同步方法达到同步的目的。
- 一个线程访问一个对象的synchronized方法或者代码块的时候,其他线程访问该对象的synchronized方法或者代码块将被阻塞,但是非synchronized方法或者代码块还是可以访问 的。
- 不论sychronized 放在对象还是方法上,如果它作用的是非静态的,那么获得锁是对象,如果是静态的,那么获得锁是类,最后导致获得所有对象的锁。
锁的升级和对比
锁一共有四种状态:
- 无锁
- 偏向锁
- 轻量级锁
- 重量级锁
锁的升级
锁可以升级,但是不能降级。
这样的规则目的是为了提高获得锁和释放锁的效率。
偏向锁
作用
大多数情况下不存在锁的竞争,为了降低同一线程获得锁的开销,就在锁的对象头中加入这一线程的ID,这样,在之后这个线程进入和退出同步块的时候就不需要CAS操作来实现加锁和解锁。
撤销
当出现锁的竞争,持有偏向锁的线程才会释放锁,锁就会升级。
轻量级锁
作用
利用CAS算法,线程通过自旋的方式获取锁。这样,线程不会被阻塞。
加锁
首先JVM在线程的栈帧中创建锁记录存储空间,然后把锁对象头重的Markword复制到栈帧中。在通过利用CAS方法将锁对象的markword替换为指向线程栈帧锁记录的指针。如果成功替换,就获得了当前锁,如果已经被其他线程替换了,那么就会自旋获取锁。
解锁
将栈帧的markword再利用CAS放回对象的头中,如果失败,就说明存在锁竞争,锁就会升级为重量级锁。
锁的比较

synchronized使用
修饰方法和代码块
修饰方法很简单,就在方法前面加一个synchronized关键字。
public synchronized void method()
{
// todo
}
public void method()
{
synchronized(this) {
// todo
}
}
指定给某个对象加锁
public void method3(SomeObject obj)
{
//obj 锁定的对象
synchronized(obj)
{
// todo
}
}
上面的代码中,通过synchronized 给obj对象加锁。当其他线程想要访问obj,就会被阻塞。
class Test implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance变量
public void method()
{
synchronized(lock) {
// todo 同步代码块
}
}
public void run() {
}
}
如果只是想要一个锁,可以利用特殊的实例来充当锁。
修饰静态的方法
public synchronized static void method() {
// todo
}
因为静态方法是属于这个类的, 而不是实例化的对象,所以,synchronized 修饰的是静态方法锁定的这个类的所有对象。
修饰类
class ClassName {
public void method() {
synchronized(ClassName.class) {
// todo
}
}
}
和修饰静态方法一样,所有对象都共有这把类锁。
参考: link.
Java并发编程的艺术(三)——synchronized的更多相关文章
- Java并发编程的艺术(三)——volatile
1. 并发编程的两个关键问题 并发是让多个线程同时执行,若线程之间是独立的,那并发实现起来很简单,各自执行各自的就行:但往往多条线程之间需要共享数据,此时在并发编程过程中就不可避免要考虑两个问题:通信 ...
- Java并发编程的艺术(六)——线程间的通信
多条线程之间有时需要数据交互,下面介绍五种线程间数据交互的方式,他们的使用场景各有不同. 1. volatile.synchronized关键字 PS:关于volatile的详细介绍请移步至:Java ...
- 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
<Java并发编程实战>和<Java并发编程的艺术> Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...
- 读《Java并发编程的艺术》(一)
离开博客园很久了,自从找到工作,到现在基本没有再写过博客了.在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜.所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督 ...
- Java并发编程的艺术,解读并发编程的优缺点
并发编程的优缺点 使用并发的原因 多核的CPU的背景下,催生了并发编程的趋势,通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升. 在特殊的业务场景下先天的就适合于并发编程. 比如在 ...
- 读书笔记之《Java 并发编程的艺术》
一.多线程语义 即使是单核处理器也支持多线程执行代码,CPU 通过给每个线程分配 CPU 时间片来执行任务,当前任务执行一个时间片后会切换到下一个任务,所以 CPU 通过不停的切换线程执行. 并发执行 ...
- 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理
二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...
- java并发编程的艺术(一)---锁的基本属性
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...
- 《Java并发编程的艺术》留给自己以后看的笔记
<Java并发编程的艺术>这本书特别好,和<深入了解JAVA虚拟机>有一拼,建议做java的都看看,下面全部都是复制书中的部分内容,主要目的是做个笔记,方便以后遇到问题能找到. ...
- Java并发编程的艺术 记录(一)
模拟死锁 package com.gjjun.concurrent; /** * 模拟死锁,来源于<Java并发编程的艺术> * @Author gjjun * @Create 2018/ ...
随机推荐
- Electron 的断点续下载
最近用 Electron 做了个壁纸程序,需要断点续下载,在这里记录一下. HTTP断点下载相关的报文 Accept-Ranges 告诉客户端服务器是否支持断点续传,服务器返回 Content-Ran ...
- java实现 阿拉伯数字转换为汉字数字(转载)
public class VedioExtractSpeech { public static void main(String[] args) { System.out.println(" ...
- 精尽 MyBatis 源码分析 - 整体架构
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 即时编译器 (JIT) 详解
最近听我的导师他们讨论Java的即时编译器(JIT),当时并不知道这是啥东西,所以就借着周末的时间,学习了一下! 一.概述 在部分的商用虚拟机(Sun HotSpot)中,Java程序最初是通过解释器 ...
- Python 调用Get接口
import requests,jsonurl = 'http://localhost:30627/api/jobs/GetNuberId?id=2'req = requests.get(url)re ...
- 记php多张图片 合并生成竖列 纵向长图(可用于商品详情图合并下载)
<?php namespace app\mapi\common\image; /** * 拼接多幅图片成为一张图片 * * 参数说明:原图片为文件路径数组,目的图片如果留空,则不保存结果 * * ...
- Fruity Granulizer合成器功能简介
本章节采用图文结合的方式给大家介绍电音编曲软件-FL Studio的插件Fruity Granulizer合成器,感兴趣的朋友可以一起沟通交流. Fruity Granulizer合成器是一个使用了粒 ...
- 【性能测试】【locust】快速入门
简介 locust是一个开源的分布式用户负载压力测试工具,对网站(其他系统,例如接口等)进行负载测试,并确定可以处理多少的并发用户,locust特点利用了协程支持,达到高数量级别的并发,以及基于事件驱 ...
- Hadoop优化之数据压缩
bBHadoop数据压缩 概述 运行hadoop程序时,I/O操作.网络数据传输.shuffle和merge要花大量的时间,尤其是数据规模很大和工作负载密集的情况下,这个时候,使用数据压缩可以提高效率 ...
- 自学linux——1.VMware的安装及VM下centos的安装
1.CentOS下载 网址:https://www.centos.org/download/ 网盘:https://pan.baidu.com/s/1HrtK6xNig6KC8oh6O-6fyg 提取 ...