博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
详解synchronized
阅读量:6613 次
发布时间:2019-06-24

本文共 1804 字,大约阅读时间需要 6 分钟。

使用

synchronized是Java中的关键字,是一种同步锁。synchronized是内置的语言实现。它修饰的对象有以下几种:

1. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 锁是当前实例对象

public synchronized void accessVal(int newVal);  复制代码

2. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 锁是 Synchronized 括号里的对象

synchronized(syncObject) {      //允许访问控制的代码     }  复制代码

其他:

当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

class Foo implements Runnable {    // 特殊的instance变量    //零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:    //生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。    private byte[] lock = new byte[0];    Public void methodA() {              synchronized(lock) {         }}   复制代码

3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;锁是当前类的 Class 对象。

4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。

原理

通常说的synchronized在方法或块上加锁,这里的锁就是对象锁(当然也可以在类上面),或者叫重量锁,在JVM中又叫对象监视器(Monitor),就是对象来监视线程的互斥。

对象在堆里的逻辑结构:

对象头的结构:
其中Tag的2bit用来显示锁类型。通常我们说synchronized的对象锁,就是这里Tag=10时的monitor对象,这里的Monitor address就是这个monitor对象(就是重量锁)的地址。
加锁的过程很简单:在当前线程的栈帧(stack frame)中生成一个锁记录(lock record),它只是对象头的一个拷贝。然后把对象头里的tag改成00,并把这个栈帧里的lock record地址放入对象头里。若操作成功,那就完成了轻量锁操作。如果不成功,说明有线程在竞争,则需要在当前对象上生成重量锁来进行多线程同步,然后将Tag状态改为10,并生成Monitor对象(重量锁对象),对象头里也会放入Monitor对象的地址。最后将当前线程t排队队列中。当synchronized区域长期都由同一个线程加锁、解锁时,jvm就用偏向锁来做,它的加锁解锁比轻量锁操作起来指令更加简化。不过一旦有其他线程使用synchronized区域,即使没有线程间竞争,也会把偏向锁升级为轻量锁,当然如果发生线程竞争就再升级为对象锁。

synchronized与Lock的区别

  • Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

  • synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

  • Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

  • 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  • Lock可以提高多个线程进行读操作的效率。

  • 在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

转载地址:http://poeso.baihongyu.com/

你可能感兴趣的文章
MyEclipse Spring开发教程:用Spring创建iPhone App(2/2)
查看>>
DevExpress v17.2新版亮点——CodeRush篇(一)
查看>>
Oracle之备份还原
查看>>
Linux 操作命令 cat
查看>>
王硕的微博
查看>>
jQuery EasyUI 重写datagrid的datetimebox编辑类型
查看>>
python基础之函数
查看>>
mysql大数据量使用limit分页,随着页码的增大,查询效率越低下
查看>>
用户组权限和ACL访问控制列表
查看>>
G盘设备未就绪数据怎么找到
查看>>
Linux-软链接、硬链接
查看>>
有趣的角度:《权力的游戏》少儿不宜数据盘点
查看>>
【api】Java在线api地址
查看>>
使用 haproxy 搭建 web 群集
查看>>
过滤空行的几种方法
查看>>
Java:银行利率
查看>>
php单文件上传和多文件上传
查看>>
直击东京产交会,弘瑞(HORI)在国际舞台展示3D打印魅力
查看>>
自定义容器
查看>>
什么是堆排序,浅而易懂的对话告诉你!
查看>>