Homework 7 Version 0 |
|
👤 Author: by 804824950qqcom 2020-11-10 07:32:10 |
Four necessary conditions:
Mutual exclusion: The resource lock is exclusive, and only one thread can own the resource during the lock period. Other threads can only try to acquire the resource after waiting for the lock to be released.
Request and hold: The current thread already owns at least one resource, but at the same time it issues a new resource request, and the requested resource is owned by other threads. At this time, it enters the state of maintaining the current resource and waiting for the next resource.
No deprivation: The resources owned by a thread can only be released by itself, and cannot be deprived by other threads.
Cyclic waiting: Refers to multiple threads requesting each other's resources, but at the same time possessing the resources that each other needs for the next step. Form a loop, similar to 2) request and hold. But here refers to the relationship between multiple threads. It does not mean that a single thread has been waiting in a loop.
Own Code:
public class DeadLockDemo implements Runnable{
public static int flag = 1;
//static 变量是 类对象共享的
static Object o1 = new Object();
static Object o2 = new Object();
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":此时 flag = " + flag);
if(flag == 1){
synchronized (o1){
try {
System.out.println("我是" + Thread.currentThread().getName() + "锁住 o1");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "醒来->准备获取 o2");
}catch (Exception e){
e.printStackTrace();
}
synchronized (o2){
System.out.println(Thread.currentThread().getName() + "拿到 o2");//第24行
}
}
}
if(flag == 0){
synchronized (o2){
try {
System.out.println("我是" + Thread.currentThread().getName() + "锁住 o2");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "醒来->准备获取 o2");
}catch (Exception e){
e.printStackTrace();
}
synchronized (o1){
System.out.println(Thread.currentThread().getName() + "拿到 o1");//第38行
}
}
}
}
public static void main(String args[]){
DeadLockDemo t1 = new DeadLockDemo();
DeadLockDemo t2 = new DeadLockDemo();
t1.flag = 1;
new Thread(t1).start();
//让main线程休眠1秒钟,保证t2开启锁住o2.进入死锁
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.flag = 0;
new Thread(t2).start();
}
}
Explain:
When t1 is created, t1 first gets the lock of o1 and starts to sleep for 3 seconds. then
The t2 thread is created, t2 gets the lock of o2 and starts to sleep for 3 seconds. then
t1 wakes up first and prepares to take the lock of o2, finds that o2 has been locked, and can only wait for the lock of o2 to be released.
Wake up after t2, ready to take the lock of o1, find that o1 has been locked, and can only wait for the lock of o1 to be released.
t1, t2 form a deadlock.
Solution:
Once a deadlock occurs, we cannot solve it. So we can only avoid deadlocks.
Since the deadlock needs to meet four conditions, then we start with the conditions, as long as we break any rules.
(Mutual exclusion) Use mutex locks as little as possible, and can add read locks instead of write locks. Of course this cannot be avoided.
(Request and hold) The strategy of resource static allocation is adopted (the static allocation of process resources means that a process allocates all the resources it needs when it is created). We try not to let threads request multiple locks at the same time, or have a lock When the next lock cannot be requested, the wait is not kept, and the resources are released first and wait for a period of time before requesting again.
(No deprivation) Allows a process to deprive the use of resources occupied by other processes. priority.
(Waiting in a loop) Try to adjust the order of acquiring locks so that no nested resource requests occur. Join timeout.