公平锁、非公平锁
公平锁: 非常公平, 不能够插队,必须先来后到!
非公平锁:非常不公平,可以插队 (默认都是非公平)
java
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}可重入锁
可重入锁(递归锁)

Synchronized版
java
package com.mystpet.suo;
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");
}
}结果:
java
A sms
A call
B sms
B calllock版:
java
package com.mystpet.suo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo02 {
public static void main(String[] args) {
Phone2 phone2=new Phone2();
new Thread(() -> {
phone2.sms();
},"A").start();
new Thread(() -> {
phone2.sms();
},"B").start();
}
}
class Phone2{
Lock lock=new ReentrantLock();
public void sms(){
lock.lock(); // 细节问题:lock.lock(); lock.unlock(); // lock 锁必须配对,否则就会死在里面
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " sms");
call(); // 这里也有锁
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
lock.unlock();
}
}
public void call(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " call");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}自旋锁
spinlock

我们来定义一个锁测试
java
package com.mystpet.suo;
import java.util.concurrent.atomic.AtomicReference;
/**
* 自旋锁
*/
public class SpinlockDemo {
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);
}
}测试:
java
package com.mystpet.suo;
import java.util.concurrent.TimeUnit;
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
// ReentrantLock reentrantLock = new ReentrantLock();
// reentrantLock.lock();
// reentrantLock.unlock();
//底层使用自旋锁
SpinlockDemo spinlockDemo = new SpinlockDemo();
SpinlockDemo lock = new SpinlockDemo();
new Thread(() -> {
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.myUnlock();
}
}, "T1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
lock.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.myUnlock();
}
}, "T2").start();
}
}结果:
java
T1==> myLock
T2==> myLock
T1==> myUnlock
T2==> myUnlock死锁
死锁是什么

死锁测试,怎么排除死锁:
java
package com.mystpet.suo;
import java.util.concurrent.TimeUnit;
public class DeadLockDemo {
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) {
throw new RuntimeException(e);
}
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "lock:" + lockB + "=>get" + lockA);
}
}
}
}解决问题
1、使用 jps -l 定位进程号 
2、使用 jstack 进程号 找到死锁问题

面试,工作中! 排查问题:
1、日志 9人回答
2、堆栈 1人回答