synchronized和lock应该是最常用的锁,今天讲这2个原理和比较。我不粘贴也不摘抄,完全是按我自己理解来说,努力做到大白话。
一、synchronized原理
说原理之前先说synchronized4个状态,因为不同状态的实现原理不同。锁的状态分为无锁->偏向锁->轻量级锁->重量级锁
①无锁状态
初始化时候状态
②偏向锁
当只有一个线程进入synchronized块,没有竞争的情况,就进入偏向锁状态。该线程只有第一次进入时候才会需要同步操作,后续就不需要同步操作,这也是java对synchronized优化操作。
③轻量级锁
当有2个线程同时请求synchronized块,那么java并不会马上变为重级锁,而是用轻量锁。轻量锁原理就是cas实现的自旋锁。
④重量级锁
当线程大于2或者轻量锁自旋次数达到一定次数,synchronized会转变为重级锁。这里要说一个东西,每个对象都有一个对象头,对象头里有一个markdown的东西,这个东西里头指向一个monitor(每个对象都有一个独立的monitor),这个monitor里头有个valatile的int。当第一个线程进入时候会把这个int置1,重入时候会再加1,其余线程判断只要!=0就说明有线程占用了该锁。
二、lock原理
首先lock分为公平锁和非公平锁,默认是非公平。公平和非公平区别就是是否可以插队。
lock也有一个valatile的state(int 类型),cas给state置1,并且记录下当前线程(用于重入锁判断)。重点是acquire这个方法。我们重点看看。
这个截图是在aqs里,说明lock原理用到了aqs(aqs就是JUC的并发框架,分为共享和独占,lock用的是共享模式)。lock在这里重写了tryacquire方法,acquireQueued方法是加入队列,exclusive是独占的意思,说明以独占方式如队列。先来看看tryacquire方法。
里头实现非常简单,第一个if和上面一样进行一次cas,第二个if是重入锁的处理。
释放锁时候会唤醒队列第一个元素,然后再进行上述操作,这里就不贴图了。
三、一些东西的区别
①synchronized和lock区别
synchronized是关键字,lock是工具包。这就注定了lock有更多的功能
②sleep和wait的区别
sleep是Thread的方法只会让出cpu并不会让出锁,而wait2个都让出
③wait和await区别
notifyall无法控制唤醒wait的执行顺序,但是lock可以new多个condition,也就是说可以用condition唤醒你要唤醒的await