12

在 Java 多线程中避免死锁情况的策略之一是使用超时。假设,一个线程已经获得了一个资源的锁,现在正在等待另一个资源的锁。在一定时间后,如果它无法获得资源 2 上的锁,则它应该停止等待资源 2 上的锁。它还应该释放对资源 1 的锁定。这样就可以避免死锁。

但是如何在 Java 中实现呢?如何显式“释放”锁?如何定义超时等待锁定。

什么是确切的 java 命令和语法。请问有什么好世界的例子吗?

4

4 回答 4

10

这是一个人为的示例,其中包含 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();
            }
        }
    };
}
于 2012-12-06T10:35:14.983 回答
3

锁定Java

Use tryLock(timeout, timeunits);

如果在给定的等待时间内空闲并且当前线程没有被中断,则获取锁。如果锁可用,则此方法立即返回值。true

如果锁不可用,则当前线程将被禁用以用于线程调度目的并处于休眠状态,直到发生以下三种情况之一:

锁被当前线程获取;

或者其他一些线程 中断当前线程,支持中断获取锁;

或 指定的等待时间已过

于 2012-12-06T10:25:10.753 回答
3

这可能会有所帮助,

Lock lock = null;
lock=....;
if (lock.tryLock(15L, TimeUnit.SECONDS)) {
    try {
       ........
    } finally {
        lock.unlock();
    }
} else {
      // do sumthing
}
于 2012-12-06T10:30:47.263 回答
3

Java 8+ 并发 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 秒的时间到期。

于 2018-01-29T10:40:48.247 回答