如何在java中进行多线程解锁线程

时间:2013-06-15 18:58:15

标签: java multithreading

在业务流程的某个地方,我的线程被锁定了。所以在那之后一切都将处于等待状态。如果它是这样的,那么我如何继续而不暂停应用程序。 这意味着我不想终止该应用程序。实际上是一个面试问题。

2 个答案:

答案 0 :(得分:1)

首先,强烈建议您仔细阅读deadlocks维基百科条目。特别是关于deadlock handling的部分。

如果这是一个面试问题,那么面试官可能对候选人对死锁如何发生以及如何预防和/或解决死因的了解更感兴趣。

这是使用同步对象集创建java死锁的基本示例

private static void synchronizedBlockDeadlock()
{
    final Object resource1 = new Object();
    final Object resource2 = new Object();

    Runnable thread1 = new Runnable()
    {

        public void run()
        {
            synchronized (resource1)
            {
                final int sleepTimeMs = 1000;
                try
                {
                    Thread.sleep(sleepTimeMs);
                }
                catch (InterruptedException e) {}

                synchronized (resource2)
                {
                    System.out.println("In thread1");
                }
            }
        }
    };

    Runnable thread2 = new Runnable()
    {

        public void run()
        {
            synchronized (resource2)
            {
                final int sleepTimeMs = 1000;
                try
                {
                    Thread.sleep(sleepTimeMs);
                }
                catch (InterruptedException e) {}

                synchronized (resource1)
                {
                    System.out.println("In thread2");
                }
            }
        }
    };

    new Thread(thread1).start();
    new Thread(thread2).start();
}

首先,两个线程(有效地)同时运行。线程1将获取对资源1的锁定并暂时休眠,使得线程2将获得对资源2的锁定。这当然是基于假设线程2能够在线程1中的睡眠调用返回之前启动。现在,线程2尝试获取由线程1保持的资源1上的锁,因此它无限期地阻塞。线程1唤醒并尝试获取资源2上的锁,该资源由线程2保持。两个线程都被阻塞,因此所有线程都被死锁。

现在,可以重新编写此代码以使用显式锁来防止死锁(而不是通过'synchronized'关键字对资源对象实例进行隐式锁定。)

请参阅以下代码:

private static void explicitLockDeadlock()
{
    final Lock lock1 = new ReentrantLock();
    final Lock lock2 = new ReentrantLock();

    Runnable thread1 = new Runnable()
    {

        public void run()
        {
            try
            {
                lock1.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-1: Lock 1 acquired");

                final int sleepTimeMs = 1000;
                Thread.sleep(sleepTimeMs);

                lock2.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-1: Lock 2 acquired");
            }
            catch (InterruptedException e) {}
            finally
            {
                lock1.unlock();
            }

            System.out.println("In thread1");
        }
    };

    Runnable thread2 = new Runnable()
    {

        public void run()
        {
            try
            {
                lock2.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-2: Lock 2 acquired");

                lock1.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-2: Lock 1 acquired");
            }
            catch (InterruptedException e) {}
            finally
            {
                lock2.unlock();
            }

            System.out.println("In thread2");
        }
    };

    new Thread(thread1).start();
    new Thread(thread2).start();
}

这种方法是抢占线程的一个实例,该线程可能会死锁,或者破坏4 Coffman conditions的“无抢占”条件。实际上,等待的'tryLock'调用在指定的时间段后过期,从而阻止应用程序无限期挂起。

答案 1 :(得分:0)

使用jps或任务管理器获取进程ID,然后使用jstack -F <pid>获取所有线程的堆栈跟踪和锁定信息(包括有关检测到的死锁的一些提示)。