各种锁的理解
公平锁,非公平锁
公平锁:非常公平,不能插队,必须先来后到
public ReentrantLock() { sync = new NonfairSync(); }
非公平锁(默认):非常不公平,允许插队,可以改变顺序
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
可重入锁(递归锁)
Synchonized 锁(默认是非公平,也是可重入锁)
public class Demo01 { public static void main(String[] args) { Phone phone = new Phone(); new Thread(()->{ phone.sms(); },"A").start(); new Thread(()->{ phone.sms(); },"B").start(); } } class Phone{ public synchronized void sms(){ System.out.println(Thread.currentThread().getName()+"=> sms"); call();//这里也有一把锁 } public synchronized void call(){ System.out.println(Thread.currentThread().getName()+"=> call"); } }
Lock 锁
//lock public class Demo02 { public static void main(String[] args) { Phone2 phone = new Phone2(); new Thread(()->{ phone.sms(); },"A").start(); new Thread(()->{ phone.sms(); },"B").start(); } } class Phone2{ Lock lock=new ReentrantLock(); public void sms(){ lock.lock(); //细节:这个是两把锁,两个钥匙 //lock锁必须配对,否则就会死锁在里面 try { System.out.println(Thread.currentThread().getName()+"=> sms"); call();//这里也有一把锁 } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void call(){ lock.lock(); try { System.out.println(Thread.currentThread().getName() + "=> call"); }catch (Exception e){ e.printStackTrace(); } finally { lock.unlock(); } } }
lock锁必须配对,相当于lock和 unlock 必须数量相同;
在外面加的锁,也可以在里面解锁;在里面加的锁,在外面也可以解锁;
自旋锁
spinlock
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
自我设计自旋锁
//自旋锁 public class SpinLock { // int 0 // Thread null AtomicReference<Thread> atomicReference = new AtomicReference<>(); // 加锁 public void myLock(){ Thread thread = Thread.currentThread(); System.out.println(Thread.currentThread().getName() + "===> myLock"); // 自旋锁(等待解锁) //如果是空的,就把当前线程放进去,无限循环 while (!atomicReference.compareAndSet(null, thread)){ } } // 解锁(不需要自旋) public void myUnlock() { Thread thread = Thread.currentThread(); System.out.println(Thread.currentThread().getName() + "===> myUnlock"); atomicReference.compareAndSet(thread, null); } }
测试:
public class TestSpinLock { public static void main(String[] args) throws InterruptedException { /*ReentrantLock reentrantLock = new ReentrantLock(); reentrantLock.lock(); reentrantLock.unlock();*/ // 底层使用自旋锁CAS SpinLock spinLock = new SpinLock(); new Thread(()->{ spinLock.myLock(); try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { spinLock.myUnlock(); } },"t1").start(); TimeUnit.SECONDS.sleep(1); new Thread(()->{ spinLock.myLock(); try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { spinLock.myUnlock(); } },"t2").start(); } }
t2进程必须等待t1进程Unlock后才能拿到锁,才能Unlock,在这之前T2进行自旋等待。。。。
死锁
public class DeadLock {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
new Thread(new MyThread(lockA,lockB),"t1").start();
new Thread(new MyThread(lockB,lockA),"t2").start();
}
}
class MyThread implements Runnable{
private String lockA;
private String lockB;
public MyThread(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run() {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName()+"lock: "+lockA+"=>get"+lockB);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println(Thread.currentThread().getName()+"lock: "+lockB+"=>get"+lockA);
}
}
}
}
死锁排查:
1、jdk的bin目录下: 有一个jps
命令:jps -l
定位进程号
当前进程号是11456
2、使用jstack
进程进程号,找到死锁信息
在最后可以看到: