可重入锁:如果有两个同步代码块,进入它们的前提是要持有锁A,两个线程同时访问,线程1 持有锁A,线程可以访问第一个同步代码块,运行到某个时刻,这个线程要进入第二个同步代码块,因为这个线程持有锁A,所以它也可进入第二个同步代码块。线程2没有锁,被阻塞。
锁的优化
减少锁持有的时间:只在临界资源前后加上锁
减小锁的粒度:并发的hashmap 按照 段位置加上锁
读写锁替换独占锁
锁分离:对链表的操作,take, put 函数分别对链表的头指针和尾指针操作,不需要持有同一把锁。
锁粗化:虚拟机遇到一连串对同一个锁的请求和释放,虚拟机会合并这些锁请求和释放。
Java虚拟机对锁的优化
偏向锁:它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。
如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。
轻量级锁:轻量级锁是由偏向所升级来的,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁,如果加锁失败,可能会升级成为重量级锁
自旋锁:等待线程释放资源,这时为了不让线程挂起,而让这个线程空转,几个CPU周期后,线程得到资源,空转结束。
锁消除:消除在代码层面上错误添加锁操作
无锁
乐观派 悲观派
锁就是一种悲观派
比较策略CAS
CAS(V,E,N) 变量V,预期值E,新值 N,如果变量V的值和预期值E相同,那么变量V的值更新为N。
原子类的算法就是利用了CAS算法实现的 无锁策略