如何防止死锁

  1. tryLock
  2. 按经历只获取一个资源,不要同时获取多个资源
  3. 尽量按顺序上锁

总结:

  1. tryLock 方法
  2. lock方法

lock是无条件阻塞加锁,tryLock 的话是 可以被打断的,被中断的

用 tryLock 可以实现一个自旋锁

1
2
3
while(!reentrantLock.tryLock()) {
     do_Something();
}

如何查看线程死锁

  1. 用 jstack 命令进行查看, jstack 命令会显示死锁的线程
  2. 两个线程操作数据库,数据库死锁的问题

任务管理器 找到 java.exe 几个进程的 PID ,一个个去试

image-20210927223532298

 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
jstack 20520 | BLOCKED
:<<EOF
 jstack 20520 | findstr BLOCKED
   java.lang.Thread.State: BLOCKED (on object monitor)
   java.lang.Thread.State: BLOCKED (on object monitor)

EOF

# 这里我是 windows 环境,linux 用 grep

jstack 20520 | findstr deadlock

:<<EOF
Found one Java-level deadlock:
Found 1 deadlock.

EOF



:<<EOF

Found one Java-level deadlock:
=============================
"Thread2":
  waiting to lock monitor 0x00000000215e35c8 (object 0x00000007404ebfc8, a java.lang.String),
  which is held by "Thread1"
"Thread1":
  waiting to lock monitor 0x00000000235a3158 (object 0x00000007404ec000, a java.lang.String),
  which is held by "Thread2"

Java stack information for the threads listed above:
===================================================
"Thread2":
        at Main$DeadLockSample.run(Main.java:38)
        - waiting to lock <0x00000007404ebfc8> (a java.lang.String)
        - locked <0x00000007404ec000> (a java.lang.String)
"Thread1":
        at Main$DeadLockSample.run(Main.java:38)
        - waiting to lock <0x00000007404ec000> (a java.lang.String)
        - locked <0x00000007404ebfc8> (a java.lang.String)

EOF

查看数据库死锁

1
2
3
4
5
6
7
8
# 查看是否锁表
show open tables where in_use > 0
show processlist;
# 查看进程
select * from information_schema.INNODB_LOCKS;

# 查看等待锁的事务
select * from information_schema.INNODB_LOCK_WAITS;

线程之间如何进行通讯

  1. 线程之间可以通过共享内存 或基于网络进行通讯
  2. 如果通过共享内存通讯,就要考虑并发问题,什么时候阻塞
  3. 像 java中的 wait,notify 就是阻塞和唤醒
  4. 通过网络就比较简单了, 网络连接发送数据给对方 【也要考虑并发加锁问题】