在多线程编程中,锁是经常使用地控制并发的机制,对于临界区的资源,须要保证线程之间互斥地访问。java
可重入锁,也叫作递归锁,指的是屡次对同一个锁进行加锁操做,都不会阻塞线程。实现思路:记录当前锁正在被哪一个线程使用,采用计数来统计lock和unlock的调用次数。正常状况下,lock和unlock的调用次数应该相等,若是不相等就会死锁。面试
public class Test implements Runnable { ReentrantLock lock = new ReentrantLock(); //定义一个可重入锁 public void get() { lock.lock(); //第一次调用lock() System.out.println(Thread.currentThread().getId()); set(); lock.unlock(); } public void set() { lock.lock(); //第二次调用lock(),并且会成功,说明lock是可重入锁 System.out.println(Thread.currentThread().getId()); lock.unlock(); } @Override public void run() { get(); } public static void main(String[] args) { Test ss = new Test(); new Thread(ss).start(); new Thread(ss).start(); new Thread(ss).start(); } }
首先,看看初级的自旋锁实现方式:编程
public class SpinLock { private AtomicReference<Thread> owner =new AtomicReference<>(); public void lock(){ Thread current = Thread.currentThread(); while(!owner.compareAndSet(null, current)){ } } public void unlock (){ Thread current = Thread.currentThread(); owner.compareAndSet(current, null); } }
实现思路:经过CAS(CompareAndSet)原子操做来更新变量。若是CAS返回true,表示得到了锁;不然,须要经过while循环检查,直到得到锁为止,这也是为何叫作自旋锁的缘由,须要不停的尝试获取锁。多线程
public class SpinLock { private AtomicReference<Thread> owner =new AtomicReference<>(); private int count =0; public void lock(){ Thread current = Thread.currentThread(); if(current==owner.get()) { count++; return ; } while(!owner.compareAndSet(null, current)){ } } public void unlock (){ Thread current = Thread.currentThread(); if(current==owner.get()){ if(count!=0){ count--; }else{ owner.compareAndSet(current, null); } } } }