理解高并发(5).synchronized原理及用法

来源:互联网 发布:linux常用命令mkdir 编辑:程序博客网 时间:2024/06/05 15:46
历史最优久的使用最方便的线程同步的关键字。必须点赞
一、synchronized 特性
  • 同一时刻只有一个线程访问临界资源
  • 其它未获取到锁执行权的线程必须排队等待
  • 保证共享资源的原子性、可见性和有序性
  • 进入synchronized范围内自动加锁,synchronized作用域外锁自动消除,即使异常也会释放锁
  • 简单方便(不需要人工释放锁)
  • jdk1.6后性能做了很大优化

二、synchronized用法
  • 普通方法同步
作用: 所有访问该对象实例该方法的线程,必须排队执行
如: synchronized public void add(){
}
  • 静态方法同步
作用: 所有采用类名.方法名访问的线程, 必须排队执行
如: synchronized public static void add(){
}
  • 代码块同步
作用: 所有访问到该表达式的线程,必须排队执行
synchronized(表达式){
}
        表达式可以是:
        a. this                 表示该对象,仅适用于非静态方法的情况
        b. 类名.class        适用于静态方法和非静态方法
c. 对象实例           适用于静态方法和非静态方法
d. 成员变量         适用于静态方法和非静态方法

三、 synchronized原理
synchronized的底层实现原理都是通过对象头里面的monitor(监视器锁)来实现的。每个对象头里面都有一个指针指向monitor,monitor中又包含有访问计数器,能否进入是根据计数器值来判断的。

  • 同步代码块原理
同步代码块是通过monitorenter、monitorexit来控制。 字节码指令如下, 操作原理:
1、当访问到monitorenter时, 当前线程会尝试获取该对象的monitor所有权
获取所有权的依据是monitor的计数器值是否为0, 为0则获取到了,同时将计数器值 +1
2、如果已获取到monitor所有权, 则直接将计数器 +1并进入运行指令阶段
3、如果没有尝试获取该对象的monitor持有权,会进入等待队列进行阻塞
  • 同步方法原理
同步方法是通过方法常量池中的方法表关键字来控制, 如果用synchronized修改方法,那么常量池里面会有ACC_SYNCHRONIZEDR进行修饰。
当线程访问加了synchronized的方法时, 会去判断是否有ACC_SYNCHRONIZED标识,
1、如果有该标识, 当前线程会尝试获取该对象的monitor所有权
获取所有权的依据是monitor的计数器值是否为0, 为0则获取到了,同时将计数器值 +1
2、如果已获取到monitor所有权, 则直接将计数器 +1并进入运行指令阶段
3、如果没有尝试获取该对象的monitor持有权,会进入等待队列进行阻塞

四、synchronized可重入性
可重入性也是依据是否可获取monitor持有权来判断。
原创粉丝点击