使用Timeout避免Java多线程中的死锁

时间:2012-12-06 10:21:46

标签: java multithreading locking timeout deadlock

避免Java多线程中死锁情况的策略之一是使用超时。 假设,一个线程已获得对一个资源的锁定,现在正在等待另一个资源上的锁定。经过一段时间后,如果无法获取资源2上的锁,那么它应该停止等待资源2的锁定。它也应该释放对resource1的锁定。因此,将避免死锁。

但是如何在Java中实现它?如何明确“释放”锁定?如何定义等待锁定的超时。

什么是精确的java命令和语法。请问任何你好世界的例子吗?

4 个答案:

答案 0 :(得分:9)

这是一个人为的例子,有2个锁和2个线程,试图以不同的顺序获取它们。没有超时,代码就会死锁。

public static void main(String[] args) throws Exception {
    final ReentrantLock lock1 = new ReentrantLock();
    final ReentrantLock lock2 = new ReentrantLock();
    Runnable try1_2 = getRunnable(lock1, "lock 1", lock2, "lock 2");
    Runnable try2_1 = getRunnable(lock2, "lock 2", lock1, "lock 1");
    new Thread(try1_2).start();
    new Thread(try2_1).start();
}

private static Runnable getRunnable(final ReentrantLock lock1, final String lock1Name, final ReentrantLock lock2, final String lock2Name) {
    return new Runnable() {
        @Override
        public void run() {
            try {
                if (lock1.tryLock(1, TimeUnit.SECONDS)) {
                    System.out.println(lock1Name + " acquired in thread " + Thread.currentThread());
                    if (lock2.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println(lock2Name + " acquired in thread " + Thread.currentThread());
                        Thread.sleep(2000);
                    } else {
                        System.out.println("Could not acquire "+lock2Name + " in thread " + Thread.currentThread());
                        lock1.unlock();
                        System.out.println(lock1Name + " released in thread " + Thread.currentThread());
                    }
                } else {
                    System.out.println("Could not acquire " + lock1Name + " in thread " + Thread.currentThread());
                }
            } catch (InterruptedException e) {
                //you should not ignore it
            } finally {
                if (lock1.isHeldByCurrentThread()) lock1.unlock();
                if (lock2.isHeldByCurrentThread()) lock2.unlock();
            }
        }
    };
}

答案 1 :(得分:3)

Lock in Java

Use tryLock(timeout, timeunits);
  

如果在给定的等待时间免费,则获取锁定   当前线程尚未中断。如果锁定可用   方法返回立即,其值为true

     

如果没有锁定   可用,然后线程的当前线程变为禁用   调度目的和休眠直到三件事之一   发生的情况:

     

当前线程锁定获取;

     

或其他一些帖子   中断当前线程,锁定获取中断   支持的;

     

或指定的等待时间

答案 2 :(得分:3)

可能有帮助,

Lock lock = null;
lock=....;
if (lock.tryLock(15L, TimeUnit.SECONDS)) {
    try {
       ........
    } finally {
        lock.unlock();
    }
} else {
      // do sumthing
}

答案 3 :(得分:0)

Java 8+ Concurrency API中,您可以设置lock在设置条件时等待的明确时间:

private Lock lock = new ReentrantLock();
private Condition myCondition = lock.newCondition();

try{            
    myCondition.await(1200L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
    System.out.println((e);
} finally{
    lock.unlock();
}

锁定将等待,直到它从另一个线程收到signal()signalAll()或者直到1.2秒的时间到期。