Skip to content

Commit 0a48130

Browse files
Dead Lock
1 parent 708b400 commit 0a48130

11 files changed

+646
-1
lines changed

DeadLock/DeadLock.iml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
7+
</content>
8+
<orderEntry type="inheritedJdk" />
9+
<orderEntry type="sourceFolder" forTests="false" />
10+
</component>
11+
</module>

DeadLock/src/DeadLockSummary.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* 死锁总结
3+
*
4+
* @Author: zzStar
5+
* @Date: 10-20-2020 14:51
6+
*/
7+
public class DeadLockSummary {
8+
9+
/**
10+
* 1.发生在并发中
11+
* 2.互不相让
12+
* 3.如果多个线程之间的依赖关系是环形,存在环路的锁的依赖关系,也可能会发生死锁
13+
*/
14+
15+
16+
/**
17+
* 死锁发生的4个必要条件
18+
* -> 互斥条件
19+
* -> 请求与保持条件
20+
* -> 不剥夺条件
21+
* -> 循环等待条件
22+
*/
23+
24+
25+
/**
26+
* 进餐问题的解决方案
27+
* -> 服务员见检查(避免策略)
28+
* -> 改变一个哲学家拿叉子的顺序(避免策略)
29+
* -> 餐票(避免策略)
30+
* -> 领导调节(检测与恢复策略)
31+
*/
32+
33+
34+
/**
35+
* 避免死锁的tips
36+
* -> 设置超时时间(tryLock(long timeout,TimeUnit unit)),synchronized不具备尝试锁的能力
37+
* -> 多使用并发类,而不是自己设计锁(如ConcurrentHashMap,juc.atomic)
38+
* -> 尽量降低锁的使用粒度:用不同的锁而不是一个锁
39+
* -> 如果能使用同步代码块,就不使用同步方法:自己指定锁对象
40+
* -> 新建线程起有意义的名字,便于排查
41+
* -> 避免锁的嵌套
42+
* -> 分配资源前先看能不能收回来:银行家算法
43+
* -> 尽量不要几个功能用同一把锁:专锁专用
44+
*/
45+
46+
47+
/** 其他活跃性问题
48+
* 活锁 -> 虽然线程并没有阻塞,也始终在运行,但是程序却得不到进展,因为线程始终重复做同样的事
49+
* 饥饿 -> 当线程需要某些资源(例如CPU),但是却始终得不到
50+
* -> 如线程的优先级设置得过于低,或者某些线程持有锁同时又无限循环从而不释放锁,或者某程序始终占用某文件的写锁
51+
*/
52+
53+
/**
54+
* 活锁
55+
* 原因:重试机制不变,消息队列始终重试
56+
* 解决:以太网的指数退避算法,加入随机因素
57+
*/
58+
59+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* 哲学家进餐问题导致的死锁
3+
*
4+
* @Author: zzStar
5+
* @Date: 10-21-2020 08:41
6+
*/
7+
public class DinningPhilosophers {
8+
9+
public static void main(String[] args) {
10+
Philosopher[] philosophers = new Philosopher[5];
11+
Object[] chopsticks = new Object[philosophers.length];
12+
// 初始化筷子
13+
for (int i = 0; i < chopsticks.length; i++) {
14+
chopsticks[i] = new Object();
15+
}
16+
for (int i = 0; i < philosophers.length; i++) {
17+
Object leftChopstick = chopsticks[i];
18+
Object rightChopstick = chopsticks[(i + 1) % chopsticks.length];
19+
philosophers[i] = new Philosopher(leftChopstick, rightChopstick);
20+
new Thread(philosophers[i], "哲学家" + (i + 1) + "号").start();
21+
}
22+
}
23+
24+
public static class Philosopher implements Runnable {
25+
private Object leftChopstick;
26+
private Object rightChopstick;
27+
28+
public Philosopher(Object leftChopstick, Object rightChopstick) {
29+
this.leftChopstick = leftChopstick;
30+
this.rightChopstick = rightChopstick;
31+
}
32+
33+
@Override
34+
public void run() {
35+
try {
36+
while (true) {
37+
doAction("Thinking");
38+
synchronized (leftChopstick) {
39+
doAction("First I pick up left chopstick");
40+
synchronized (rightChopstick) {
41+
doAction("Then I get the right chopstick,so I start eating");
42+
doAction("Put down right chopstick");
43+
}
44+
doAction("Put down left chopstick");
45+
}
46+
}
47+
} catch (InterruptedException e) {
48+
e.printStackTrace();
49+
}
50+
}
51+
52+
private void doAction(String action) throws InterruptedException {
53+
System.out.println(Thread.currentThread().getName() + "" + action);
54+
Thread.sleep((long) (Math.random() * 10));
55+
}
56+
}
57+
58+
59+
}

DeadLock/src/LiveLock.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import java.util.Random;
2+
3+
/**
4+
* 演示活锁
5+
*
6+
* @Author: zzStar
7+
* @Date: 10-21-2020 10:46
8+
*/
9+
public class LiveLock {
10+
11+
static class Spoon {
12+
13+
private Diner owner;
14+
15+
public Spoon(Diner owner) {
16+
this.owner = owner;
17+
}
18+
19+
public Diner getOwner() {
20+
return owner;
21+
}
22+
23+
public void setOwner(Diner owner) {
24+
this.owner = owner;
25+
}
26+
27+
public synchronized void use() {
28+
System.out.printf("%s吃完了!", owner.name);
29+
}
30+
}
31+
32+
static class Diner {
33+
34+
private String name;
35+
private boolean isHungry;
36+
37+
public Diner(String name) {
38+
this.name = name;
39+
isHungry = true;
40+
}
41+
42+
public void eatWith(Spoon spoon, Diner spouse) {
43+
while (isHungry) {
44+
if (spoon.owner != this) {
45+
try {
46+
Thread.sleep(1);
47+
} catch (InterruptedException e) {
48+
e.printStackTrace();
49+
}
50+
continue;
51+
}
52+
// 加入随机因素解决
53+
Random random = new Random();
54+
if (spouse.isHungry && random.nextInt(10) < 9) {
55+
System.out.println(name + ": 亲爱的" + spouse.name + "你先吃吧");
56+
spoon.setOwner(spouse);
57+
continue;
58+
}
59+
60+
spoon.use();
61+
isHungry = false;
62+
System.out.println(name + ": 我吃完了");
63+
spoon.setOwner(spouse);
64+
65+
}
66+
}
67+
}
68+
69+
70+
public static void main(String[] args) {
71+
Diner husband = new Diner("牛郎");
72+
Diner wife = new Diner("织女");
73+
74+
Spoon spoon = new Spoon(husband);
75+
76+
new Thread(() -> husband.eatWith(spoon, wife)).start();
77+
78+
new Thread(() -> wife.eatWith(spoon, husband)).start();
79+
}
80+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import java.util.Random;
2+
3+
/**
4+
* 多人同时转账,依然很危险
5+
*
6+
* @Author: zzStar
7+
* @Date: 10-20-2020 15:42
8+
*/
9+
public class MultiTransferMoney {
10+
11+
private static final int NUM_ACCOUNTS = 200;
12+
private static final int NUM_MONEY = 1000;
13+
private static final int NUM_ITERATIONS = 10000;
14+
private static final int NUM_THREADS = 20;
15+
16+
public static void main(String[] args) {
17+
Random random = new Random();
18+
TransferMoney.Account[] accounts = new TransferMoney.Account[NUM_ACCOUNTS];
19+
20+
// 初始化数组
21+
for (int i = 0; i < accounts.length; i++) {
22+
accounts[i] = new TransferMoney.Account(NUM_MONEY);
23+
}
24+
25+
class TransferThread extends Thread {
26+
@Override
27+
public void run() {
28+
for (int i = 0; i < NUM_ITERATIONS; i++) {
29+
int fromAccount = random.nextInt(NUM_ACCOUNTS);
30+
int toAccount = random.nextInt(NUM_ACCOUNTS);
31+
int amount = random.nextInt(NUM_MONEY);
32+
TransferMoney.transferMoney(accounts[fromAccount], accounts[toAccount], amount);
33+
}
34+
System.out.println("over");
35+
}
36+
}
37+
38+
for (int i = 0; i < NUM_THREADS; i++) {
39+
new TransferThread().start();
40+
}
41+
}
42+
}

DeadLock/src/MustDeadLock.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* 演示死锁的发生
3+
*
4+
* @Author: zzStar
5+
* @Date: 10-20-2020 15:01
6+
*/
7+
public class MustDeadLock implements Runnable {
8+
9+
int flag = 1;
10+
11+
static Object o1 = new Object();
12+
static Object o2 = new Object();
13+
14+
public static void main(String[] args) {
15+
MustDeadLock mustDeadLock1 = new MustDeadLock();
16+
MustDeadLock mustDeadLock2 = new MustDeadLock();
17+
mustDeadLock1.flag = 1;
18+
mustDeadLock2.flag = 0;
19+
new Thread(mustDeadLock1).start();
20+
new Thread(mustDeadLock2).start();
21+
}
22+
23+
@Override
24+
public void run() {
25+
System.out.println("flag = " + flag);
26+
27+
// 两个线程进入,分别以不同的顺序拿着两把锁
28+
if (flag == 1) {
29+
synchronized (o1) {
30+
try {
31+
Thread.sleep(500);
32+
} catch (InterruptedException e) {
33+
e.printStackTrace();
34+
}
35+
synchronized (o2) {
36+
System.out.println("Thread1 get all locks");
37+
}
38+
}
39+
}
40+
41+
if (flag == 0) {
42+
synchronized (o2) {
43+
try {
44+
Thread.sleep(500);
45+
} catch (InterruptedException e) {
46+
e.printStackTrace();
47+
}
48+
synchronized (o1) {
49+
System.out.println("Thread2 get all locks");
50+
}
51+
}
52+
}
53+
}
54+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @Description: 改变拿筷子的顺序解决问题
3+
* @Author: zzStar
4+
* @Date: 2020/10/21 09:13
5+
*/
6+
public class SolveDinningPhilosophersProblem {
7+
8+
public static void main(String[] args) {
9+
Philosopher[] philosophers = new Philosopher[5];
10+
Object[] chopsticks = new Object[philosophers.length];
11+
// 初始化筷子
12+
for (int i = 0; i < chopsticks.length; i++) {
13+
chopsticks[i] = new Object();
14+
}
15+
for (int i = 0; i < philosophers.length; i++) {
16+
Object leftChopstick = chopsticks[i];
17+
Object rightChopstick = chopsticks[(i + 1) % chopsticks.length];
18+
19+
// 到了最后一位哲学家
20+
if (i == philosophers.length - 1) {
21+
philosophers[i] = new Philosopher(rightChopstick, leftChopstick);
22+
} else {
23+
philosophers[i] = new Philosopher(leftChopstick, rightChopstick);
24+
}
25+
26+
new Thread(philosophers[i], "哲学家" + (i + 1) + "号").start();
27+
}
28+
}
29+
30+
public static class Philosopher implements Runnable {
31+
private Object leftChopstick;
32+
private Object rightChopstick;
33+
34+
public Philosopher(Object leftChopstick, Object rightChopstick) {
35+
this.leftChopstick = leftChopstick;
36+
this.rightChopstick = rightChopstick;
37+
}
38+
39+
@Override
40+
public void run() {
41+
try {
42+
while (true) {
43+
doAction("Thinking");
44+
synchronized (leftChopstick) {
45+
doAction("First I pick up left chopstick");
46+
synchronized (rightChopstick) {
47+
doAction("Then I get the right chopstick,so I start eating");
48+
doAction("Put down right chopstick");
49+
}
50+
doAction("Put down left chopstick");
51+
}
52+
}
53+
} catch (InterruptedException e) {
54+
e.printStackTrace();
55+
}
56+
}
57+
58+
private void doAction(String action) throws InterruptedException {
59+
System.out.println(Thread.currentThread().getName() + "" + action);
60+
Thread.sleep((long) (Math.random() * 10));
61+
}
62+
}
63+
64+
65+
}

0 commit comments

Comments
 (0)