并发编程 线程安全——synchronized

synchronized

概述:

synchronized是Java中的关键字 可以给方法和代码块加锁 (synchronized底层好像是通过C实现的)
可以保证方法或者代码块在运行时 同一时刻只有一个线程可以进入到临界区(临界区就是synchronized锁住的区域)
Java中每一个对象都可以作为锁 这是synchronized实现同步的基础 这里需要知道的是为什么Java的每个对象都可以作为锁
因为在Java中每个对象都有一个内置锁(监视器,也可以理解成锁标记),而synchronized就是使用对象的内置锁(监视器)来将代码块(方法)锁定的

  • synchronized可以给方法和代码块加锁
  • 加锁解锁的过程都是自动的
  • synchronized关键字编译之后
    会在同步块的前后分别形成monitorentermonitorexit这两个字节码指令
    这两个字节码指令都需要一个reference类型的参数来指明要锁定和解锁的对象

示例:

// 直接加在方法上 相当于当前方法为同步方法
// 加锁对象的话 实例类是this 静态类是class对象 (区别在于 一个锁住的是一个单独的实例 一个是整个静态类对象)  
public synchronized void Test1() {
    System.out.println("-----Test1------");
}

// 直接使用synchronized关键字 实现同步代码块 加锁对象程序员指定 一般指定为this
public void Test2(){
    synchronized (this){
        System.out.println("-----Test2------");
    }
}

优点:

  • 加锁 解锁 过程都是底层帮我们处理了
  • java的关键字,jvm原生支持

缺点:

  • 效率低,试图获取锁时不能设定超时时间
    未得到锁的线程只能不停的尝试获得锁 而不能中断 高并发的情况下会导致性能下降
  • 不够灵活 只能使用某个对象作为锁 且加锁和释放的时机单一
  • 无法知道是否成功获得锁
  • 锁的类型不可更改:可重入 不可中断 非公平

优化:

synchronized 属于重量级锁 1.6后Java对他进行了优化 出现了一个锁升级的概念(锁是不能降级的
升级路线是:无锁 =》 偏向锁 =》 轻量级锁 =》 重量级锁

  • 无锁:没有线程访问同步代码块时的状态
  • 偏向锁:当有一个线程访问同步代码块时 无锁的就会升级为偏向锁 偏向当前线程(也就是第一个访问同步代码块的线程)
  • 轻量级锁:当出现锁竞争的时候 偏向锁就会升级为轻量级锁
    轻量级锁也就是自旋锁 线程会自旋十次 自旋是指竞争失败的线程循环获取锁(正常应该是竞争失败的线程阻塞)
    失败十次后 就会锁膨胀 (线程的自旋次数可以自己指定)
  • 重量级锁:在轻量级锁自旋失败后 就会升级为重量级锁 也就是synchronized本来的级别
posted @ 2021-08-12 10:08  熏晴微穗  阅读(69)  评论(0)    收藏  举报