synchronized面试整理

线程同步方法都有哪些

互斥和同步的关系

互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法控制对资源的访问顺序
同步是指在互斥的基础上实现对资源的有序访问

Synchronized底层原理 synchronized修饰方法和代码块区别

  • 定义:synchronized 实际是用对象锁保证了临界区内代码的原子性,临界区内的代码对外是不可分割的,不会被线程切换所打断。
    引出底层
  • Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现方法同步和代码块同步,但两者的实现细节不一样。

  • 代码块同步是使用monitorenter和monitorexit指令实现的,线程执行monitorenter指令时尝试获取monitor的所有权,monitorexit退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
  • 方法的同步并没有通过指令monitorenter和monitorexit来完成(理论上其实也可以通过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。
    synchronized面试整理_第1张图片

操作系统解释为什么synchronized效率低,以及引入的锁

Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。所以每一次挂起线程 唤醒线程都要进行一个操作系用的映射。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,频繁出现程序运行状态的切换,线程的挂起和唤醒,这样就会大量消耗资源,程序运行的效率低下,这就是为什么Synchronized效率低的原因。因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为“重量级锁”。
在java6之前monitor对象都是操作系统的,jdk1.6之后jvm为我们提供了偏向所和轻量级锁

介绍锁 锁升级 优缺点 使用场景

  • 偏向锁:一般对象都是默认开启偏向锁的,它在应用程序启动几秒后才激活
    发明动机: 发现不止是多线程在对锁抢夺,同一个线程下也会多次获得锁,同一个线程获得锁没必要每一次都进行cas操作,代价太大为了让线程加锁解锁的代价更小
    ,引入了偏向锁。
  • 加锁原理:
    偏行锁在对象头中的markword和栈帧的锁记录里中设置自己的线程ID 后三位是101 以后该线程再进入和退出同步代码块就不需要cas来加锁和解锁,只需要测试当前的对象的markword当中是与否有指向本线程的偏向锁即可。
  • 解锁原理:
    当有第二个线程来竞争锁的时候就会释放锁。其中有批量重偏向,0-19次的竞争都是先撤销第一个线程,40次以上就批量撤销升级为轻量级锁了。

  • 轻量级锁:
    发明动机:多线程都是对临界区交替请求,并没有产生竞争,那就希望不要都调用操作系统的重量级锁,带来状态切换的耗时以及性能的消耗。
  • 加锁:jvm会在栈帧中有一个锁记录和对象指针 对象指向所对象 对象投中的markword里面的内容会复制一份Displaced Mark Word。线程尝试用cas将markword当中的内容和锁记录进行一个交换,如果交换成功线程获得轻量级锁,如果不成功当前线程就会自旋 或者 膨胀为重量级所
  • 解锁:cas操作把displaced mark word复制回来 如果能够复制回来就解锁 不能升级为重量级所

在轻量级锁中出现了自旋锁和自适应锁,所谓的自旋,就是让没有获得锁的线程自己运行一段时间的自循环,但是自旋不进入阻塞的代价就是一直占用Cpu,如果是短时间的自旋还好,若是长时间没有获得锁,就会消耗大量的Cpu资源必须挂起,通常是10次自旋就挂起了。JDK6之后又加入了自旋适应锁,他会根据这个锁的上一次自旋时间和拥有者的状态来判断自旋的时间。


当前对象的markword指向的是monitor,monitor当中有entryset . owner. waitset
获得锁对象的owner是他,其他线程来竞争就被阻塞放入entryset中,当前的owner出取进入waitset,owner也变成了空 就阻塞线程被唤醒
synchronized面试整理_第2张图片

你可能感兴趣的:(1.多线程)