java多线程与并发(十)——设计一个死锁

自己设计一个死锁,来理解死锁的原理。
死锁的定义是,两个或两个以上的线程或进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
简化一下,就当成只有两个线程。现在有线程1和线程2。线程1执行过程中,先锁定了对象a,然后需要再锁定b才能继续执行代码;而线程2正巧相反,先锁定了b,需要再锁定a才能继续执行代码。这时,两个线程都等着对方解锁,才能继续执行,这时,两个线程就进入等待状态,最终不会有线程执行。这就变成了死锁。
代码如下:

package deadLockDemo;

public class ThreadTest {
    public static void main(String[] args){
        Thread t9=new Thread(new DeadLock(true));
        Thread t10=new Thread(new DeadLock(false));

        t9.start();
        t10.start();
    }
}
class DeadLock implements Runnable{
    boolean lockFormer;
    static Object o1=new Object();
    static Object o2=new Object();
    DeadLock(boolean lockFormer){
        this.lockFormer=lockFormer;
    }
    @Override
    public void run(){
        if(this.lockFormer){
            synchronized (o1){
                try{
                    Thread.sleep(500);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                synchronized (o2){
                    System.out.println("1ok");
                }
            }
        }else{
            synchronized (o2){
                try{
                    Thread.sleep(500);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                synchronized (o1){
                    System.out.println("2ok");
                }
            }
        }
    }
}

从以上例子中可以看出,陷入死锁是因为加了多个锁,如果尽量减少加锁,可以避免死锁。
参考https://blog.csdn.net/qq_35064774/article/details/51793656

死锁发生的原因:

1、系统资源有限

2、进程或线程推进顺序不恰当

3、资源分配不当

死锁发生的四个条件:

1、互斥条件:一份资源每次只能被一个进程或线程使用(在Java中一般体现为,一个对象锁只能被一个线程持有)

2、请求与保持条件:一个进程或线程在等待请求资源被释放时,不释放已占有资源

3、不可剥夺条件:一个进程或线程已经获得的资源不能被其他进程或线程强行剥夺

4、循环等待条件:形成一种循环等待的场景

package deadLockDemo;

public class TestDeadLock implements Runnable {

    A a = new A();
    B b = new B();

    public void init() throws InterruptedException{
        Thread.currentThread().setName("主线程");
        a.waitMethod(b);
    }

    @Override
    public void run() {
        Thread.currentThread().setName("副线程");
        try {
            b.waitMethod(a);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException{
        TestDeadLock testDeadLock = new TestDeadLock();
        Thread thread = new Thread(testDeadLock);
        thread.start();
        testDeadLock.init();
    }
}
class A {
    public synchronized void waitMethod(B b) throws InterruptedException{
        System.out.println(Thread.currentThread().getName() + ":正在执行a的等待方法,持有a的对象锁");
        Thread.sleep(2000L);
        System.out.println(Thread.currentThread().getName() + ":试图调用b的死锁方法,尝试获取b的对象锁");
        b.deadLockMethod();
    }

    public synchronized void deadLockMethod(){
        System.out.println(Thread.currentThread().getName() + ":正在执行a的死锁方法,持有a的对象锁");
    }
}
class B {
    public synchronized void waitMethod(A a) throws InterruptedException{
        System.out.println(Thread.currentThread().getName() + ":正在执行b的等待方法,持有b的对象锁");
        Thread.sleep(2000L);
        System.out.println(Thread.currentThread().getName() + ":试图调用a的死锁方法,尝试获取a的对象锁");
        a.deadLockMethod();
    }

    public synchronized void deadLockMethod(){
        System.out.println(Thread.currentThread().getName() + ":正在执行B的死锁方法,持有B的对象锁");
    }
}

通过sleep()方法,可以实现主线程持有a的对象锁并请求b的对象锁、副线程持有b的对象锁并请求a的对象锁的场景,即发生死锁。
结果如下:

D:\Java\jdk\bin\java -javaagent:D:\IdeaIU\lib\idea_rt.jar=55036:D:\IdeaIU\bin -Dfile.encoding=UTF-8 -classpath D:\Java\jdk\jre\lib\charsets.jar;D:\Java\jdk\jre\lib\deploy.jar;D:\Java\jdk\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk\jre\lib\ext\cldrdata.jar;D:\Java\jdk\jre\lib\ext\dnsns.jar;D:\Java\jdk\jre\lib\ext\jaccess.jar;D:\Java\jdk\jre\lib\ext\jfxrt.jar;D:\Java\jdk\jre\lib\ext\localedata.jar;D:\Java\jdk\jre\lib\ext\nashorn.jar;D:\Java\jdk\jre\lib\ext\sunec.jar;D:\Java\jdk\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk\jre\lib\ext\sunmscapi.jar;D:\Java\jdk\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk\jre\lib\ext\zipfs.jar;D:\Java\jdk\jre\lib\javaws.jar;D:\Java\jdk\jre\lib\jce.jar;D:\Java\jdk\jre\lib\jfr.jar;D:\Java\jdk\jre\lib\jfxswt.jar;D:\Java\jdk\jre\lib\jsse.jar;D:\Java\jdk\jre\lib\management-agent.jar;D:\Java\jdk\jre\lib\plugin.jar;D:\Java\jdk\jre\lib\resources.jar;D:\Java\jdk\jre\lib\rt.jar;G:\IntelliJ_workspace\SpringTest\out\production\SpringTest;G:\IntelliJ_workspace\SpringTest\lib\spring-instrument-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-instrument-tomcat-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-aspects-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-context-support-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-jms-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-expression-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-beans-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-jdbc-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-oxm-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-context-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-aop-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\aopalliance-1.0.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-messaging-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\commons-logging-1.2.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-test-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-tx-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-orm-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-core-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-webmvc-portlet-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-web-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-webmvc-4.3.14.RELEASE.jar;G:\IntelliJ_workspace\SpringTest\lib\spring-websocket-4.3.14.RELEASE.jar;D:\IdeaIU\lib\junit-4.12.jar;D:\IdeaIU\lib\hamcrest-core-1.3.jar deadLockDemo.TestDeadLock
主线程:正在执行a的等待方法,持有a的对象锁
副线程:正在执行b的等待方法,持有b的对象锁
主线程:试图调用b的死锁方法,尝试获取b的对象锁
副线程:试图调用a的死锁方法,尝试获取a的对象锁
    原文作者:java锁
    原文地址: https://blog.csdn.net/u010843421/article/details/81630898
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞