1、公平锁、非公平锁

公平锁: 非常公平, 不能够插队,必须先来后到!

非公平锁:非常不公平,可以插队 (默认都是非公平)

1
2
3
4
5
6
7
public ReentrantLock() {
sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

2、可重入锁

可重入锁(递归锁

image-20210328181106630

Synchronized版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Synchronized
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 版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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.lock(); lock.unlock(); // lock 锁必须配对,否
则就会死在里面
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "sms");
call(); // 这里也有锁
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
lock.unlock();
}

}

public void call(){

lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

3、自旋锁

spinlock

image-20210328181229497

自定义一个锁测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 自旋锁
*/
public class SpinlockDemo {

// 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);
}

}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
// ReentrantLock reentrantLock = new ReentrantLock();
// reentrantLock.lock();
// reentrantLock.unlock();

// 底层使用的自旋锁CAS
SpinlockDemo lock = new SpinlockDemo();

new Thread(()-> {
lock.myLock();

try {
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}

},"T1").start();

TimeUnit.SECONDS.sleep(1);

new Thread(()-> {
lock.myLock();

try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}

},"T2").start();

}
}

image-20210328181326930

4、死锁

image-20210328181339391

死锁测试,怎么排除死锁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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) {
e.printStackTrace();
}

synchronized (lockB){
System.out.println(Thread.currentThread().getName() +
"lock:"+lockB+"=>get"+lockA);
}

}
}
}

解决问题

  1. 使用 jps -l 定位进程号

image-20210328181510556

  1. 使用 jstack 进程号 找到死锁问题

image-20210328181526426

遇到问题,查看日志和堆栈。