关于java多线程死锁的问题

最近有被问到死锁的问题,目前为止我的项目还没有遇到过死锁的问题,但是对这个问题我挺感兴趣的,所以试着写了一下解决的方案。不知道实际应用中是怎么解决的呢?有什么完整的方案,希望可以在评论区告诉我。

1)第一种,一开始想到的,应该不能算是真正意义的死锁,只是锁长时间被占用

首先加了同步锁的方法如果抛出异常,锁是会自动被释放的。所以我在下面的测试代码中,使用Thread.sleep来让这个test方法一直占用锁。

解释一下下面的类的意义, test的方法是加了同步锁的方法,是我们要执行的程序。

ctime方法是用来控制每个同步进程的总体时间不要超过5000毫秒,需要单独开启一个线程去执行。

思路很简单,在同步方法开始的时候记录下当前系统的时间, 在ctime方法中写一个while循环  每间隔一秒钟更新一下当前时间。如果当前时间减去

进程的开始大于了5秒钟。就结束当前正在执行同步方法的线程。

用tcount来统计执行完毕或者中断的线程数量,如果所有的线程都结束了就跳出while循环,这样监控线程也结束了。

用一个单独的监控线程来防止死锁。会额外的占用内存。但是目前也没有想到更好的方式。有知道相关方案的欢迎评论区留言。

public class TestThread {
    static Thread nowThread;
    static TestThread testThread;
    static  int tcount;
    public synchronized void test(int a,Thread s){
        nowThread=s;

        time=System.currentTimeMillis();
        try{
            Thread.sleep(a);
            System.out.println("延时了"+a);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        tcount++;

    }
    static  long time;

    /**
     * 控制时间的方法
     */
    public void ctime(){

        if(time==0){
            time=System.currentTimeMillis();
        }
        long nowTime=System.currentTimeMillis();

        while (tcount<3){
            if(nowTime-time>5000){
                try {
                    System.out.println("执行了结束线程操作");
                    synchronized (nowThread) {
                        nowThread.interrupt();
                    }
                } catch ( Exception e) {
                    e.printStackTrace();
                    System.out.println(e.getMessage());
                }
            }
            try {
               Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nowTime=System.currentTimeMillis();
        }
        time=0;

        System.out.println("监控线程结束了");
    }

    public static void main(String [] args){
        testThread=new TestThread();
       new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    testThread.test(10000000, Thread.currentThread());
                }catch (Exception e) {
                    tcount++;
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    testThread.test(20000000,Thread.currentThread());
                }catch (Exception e) {
                    tcount++;
                }

            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    testThread.test(3, Thread.currentThread());
                }catch (Exception e){
                    tcount++;
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.ctime();
            }
        }).start();

    }

}

程序的执行结果

执行了结束线程操作
sleep interrupted
延时了3
执行了结束线程操作
sleep interrupted
监控线程结束了

2)第二种情况,真正意义的两个线程之间的死锁,这种情况我尝试了中断线程,然而如果用sychronize的关键字的话,死锁情况是无法中断的

所以最后找到了Lock类,由于Lock加锁是可以中断的,所以还是用之前的方式,超时中断,和上面的方法差不多。只不过由于需要两个锁互相等

所以改成了用两个线程监控两个锁。一旦锁长时间没有释放,就中断线程。这时候就会抛出异常,进入catch代码块。在这里释放锁,

程序里释放锁的部分之所以两个锁都释放,是出于假设不会发生死锁的命题。实际代码中由于死锁了线程1和线程2都只会拿到一个锁,所以在unlock的时候会抛异常,

所以要用trycatch捕捉异常





import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestThread {
    private Thread nowThread;
    static TestThread testThread,testThread2;
    private int tcount;

    private long time;


    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public  void setNowThread(Thread nowThread) {
        this.nowThread = nowThread;
    }

    /**
     * 控制时间的方法
     */
    public void ctime() {

        if (time == 0) {
            time = System.currentTimeMillis();
        }
        long nowTime = System.currentTimeMillis();

        while (tcount < 2) {
            if (nowTime - time > 5000) {
                try {
                    nowThread.interrupt();
                


                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println(e.getMessage());
                }
                finally {

                }
                System.out.println(tcount);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nowTime = System.currentTimeMillis();
        }

        time = 0;

        System.out.println("监控线程结束了");
    }


    static Lock lock1 = new ReentrantLock();
     static Lock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        testThread = new TestThread();
        testThread2=new TestThread();

        Thread thread;
        thread= new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    lock1.lockInterruptibly();

                        System.out.println("线程1获取锁1");
                        testThread.setTime(System.currentTimeMillis());
                        testThread.setNowThread(Thread.currentThread());
                        Thread.sleep(200);

                        lock2.lockInterruptibly();
                            System.out.println("线程1 获取锁2");
                            testThread2.setTime(System.currentTimeMillis());
                            testThread2.setNowThread(Thread.currentThread());
                        lock2.unlock();

                    System.out.println("线程1执行完毕");
                        lock1.unlock();
                } catch (Exception e) {
                    System.out.println("执行catch");
                    try {
                        lock1.unlock();//可能会抛异常,在本线程并没有给lock加锁的情况
                    }catch (Exception e1){

                    }
                    try {
                        lock2.unlock();//可能会抛异常,在本线程并没有给lock加锁的情况
                    }catch (Exception e2){

                    }
                } finally {
                    System.out.println("执行finally");
                    testThread.tcount++;
                    testThread2.tcount++;
                }

            }
        });
        thread.start();

       thread= new Thread(new Runnable() {
            @Override
            public void run() {


                try {
                    lock2.lockInterruptibly();

                        System.out.println("线程2 获取锁2");
                        testThread2.setTime(System.currentTimeMillis());
                        testThread2.setNowThread(Thread.currentThread());

                        Thread.sleep(200);
                        lock1.lockInterruptibly();
                            System.out.println("线程2 获取锁1");
                            testThread.setTime(System.currentTimeMillis());
                            testThread.setNowThread(Thread.currentThread());

                        lock1.unlock();

                    lock2.unlock();
                    System.out.println("线程2执行完毕");
                } catch (Exception e) {
                    try {
                        lock1.unlock();//可能会抛异常,在本线程并没有给lock加锁的情况
                    }catch (Exception e1){

                    }
                    try {
                        lock2.unlock();//可能会抛异常,在本线程并没有给lock加锁的情况
                    }catch (Exception e2){

                    }
                } finally {
                    testThread.tcount++;
                    testThread2.tcount++;
                }


            }
        });

        thread.start();

        thread=new Thread(new Runnable() {
            @Override
            public void run() {
                try {



                    Thread.sleep(2000);

                    lock1.lockInterruptibly();
                        System.out.println("正常执行3的1获取锁1");
                        testThread.setTime(System.currentTimeMillis());
                        testThread.setNowThread(Thread.currentThread());

                    lock1.unlock();
                    System.out.println("正常执行的需要获取锁1的程序");
                } catch (Exception e) {
                    lock1.unlock();
                } finally {
                    testThread.tcount++;
                }
            }
        });
        thread.start();

       thread= new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Thread.sleep(2000);

                    lock2.lockInterruptibly();
                        System.out.println("正常执行4获取锁2");
                        testThread2.setTime(System.currentTimeMillis());

                        testThread2.setNowThread(Thread.currentThread());

                    lock2.unlock();
                    System.out.println("正常执行的需要获取锁2的程序");
                } catch (Exception e) {
                    lock2.unlock();
                } finally {
                    testThread2.tcount++;
                }


            }
        });
        thread.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.ctime();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread2.ctime();
            }
        }).start();
    }

}

执行结果

线程1获取锁1
线程2 获取锁2
0
执行catch
1
正常执行4获取锁2
执行finally
正常执行3的1获取锁1
正常执行的需要获取锁2的程序
正常执行的需要获取锁1的程序
监控线程结束了
监控线程结束了

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值