为什么java ReentrantLock不抛出InterruptedException?
我想在Java线程并发中创建竞争条件并创建死锁。 我使用ReentrantLock,但它不会抛出InterruptedException 现在是死锁,我使用lockinterruptablely,但它不会抛出InterruptedException,有人能告诉我为什么吗为什么java ReentrantLock不抛出InterruptedException?,java,multithreading,reentrantlock,Java,Multithreading,Reentrantlock,我想在Java线程并发中创建竞争条件并创建死锁。 我使用ReentrantLock,但它不会抛出InterruptedException 现在是死锁,我使用lockinterruptablely,但它不会抛出InterruptedException,有人能告诉我为什么吗 public class Test { public static void main(String[] args) throws InterruptedException { final Obj
public class Test {
public static void main(String[] args) throws InterruptedException {
final Object o1 = new Object();
final Object o2 = new Object();
final ReentrantLock l1 = new ReentrantLock();
final ReentrantLock l2 = new ReentrantLock();
Thread t1 = new Thread() {
public void run() {
try {
l1.lockInterruptibly();
System.out.println("I am in t1 step 1 " + o1.toString());
Thread.sleep(1000);
l2.lock();
try {
System.out.println("I am in t1 step 2 " + o2.toString());
} finally {
l2.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
l2.lockInterruptibly();
System.out.println("I am in t2 step 1 " + o2.toString());
Thread.sleep(1000);
l1.lock();
try {
System.out.println("I am in t2 step 2 " + o1.toString());
} finally {
l1.unlock();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}
这两个线程在以下行中处于死锁状态:
l1.lock()
和l2.lock()
。所以当你打断他们时,他们不会做出反应。如果将所有的lock()
调用替换为lockinterruptbly()
则会出现异常
编辑:
我准备了一个更简单的示例,它将根据您的需要生成竞争条件:
public class Test {
public static void main(String[] args) throws InterruptedException {
final ReentrantLock l1 = new ReentrantLock();
final Random rn = new Random();
Thread t1 = new Thread() {
public void run() {
try {
Thread.sleep(rn.nextInt(1000)); //wait 0-999 ms
l1.lockInterruptibly();
System.out.println("Thread 1 won");
} catch (InterruptedException e) {
System.out.println("Thread 1 interrupted");
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
Thread.sleep(rn.nextInt(1000)); //wait 0-999 ms
l1.lockInterruptibly();
System.out.println("Thread 2 won");
} catch (InterruptedException e1) {
System.out.println("Thread 2 interrupted");
}
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}
使用此代码,您将在每次运行时随机获得两个输出中的一个:
Thread 1 won
Thread 2 interrupted
或
取决于生成的随机数。这两个线程在行中处于死锁状态:
l1.lock()
和l2.lock()
。所以当你打断他们时,他们不会做出反应。如果将所有的lock()
调用替换为lockinterruptbly()
则会出现异常
编辑:
我准备了一个更简单的示例,它将根据您的需要生成竞争条件:
public class Test {
public static void main(String[] args) throws InterruptedException {
final ReentrantLock l1 = new ReentrantLock();
final Random rn = new Random();
Thread t1 = new Thread() {
public void run() {
try {
Thread.sleep(rn.nextInt(1000)); //wait 0-999 ms
l1.lockInterruptibly();
System.out.println("Thread 1 won");
} catch (InterruptedException e) {
System.out.println("Thread 1 interrupted");
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
Thread.sleep(rn.nextInt(1000)); //wait 0-999 ms
l1.lockInterruptibly();
System.out.println("Thread 2 won");
} catch (InterruptedException e1) {
System.out.println("Thread 2 interrupted");
}
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}
使用此代码,您将在每次运行时随机获得两个输出中的一个:
Thread 1 won
Thread 2 interrupted
或
取决于生成的随机数。您的问题是每个线程都试图获取两个锁
// Thread 1.
l1.lockInterruptibly();
// ....
l2.lock();
// Thread 2.
l2.lockInterruptibly();
// ....
l1.lock();
因此,每个线程获取一个锁,然后尝试获取另一个线程已经持有的锁。这称为死锁
您没有看到java.lang.InterruptedException
,因为线程等待的锁(第二个)不是可中断的锁
用以下方法解决此问题:
// Thread 1.
l1.lockInterruptibly();
// ....
l2.lockInterruptibly();
// Thread 2.
l2.lockInterruptibly();
// ....
l1.lockInterruptibly();
您的问题是每个线程都试图获取两个锁
// Thread 1.
l1.lockInterruptibly();
// ....
l2.lock();
// Thread 2.
l2.lockInterruptibly();
// ....
l1.lock();
因此,每个线程获取一个锁,然后尝试获取另一个线程已经持有的锁。这称为死锁
您没有看到java.lang.InterruptedException
,因为线程等待的锁(第二个)不是可中断的锁
用以下方法解决此问题:
// Thread 1.
l1.lockInterruptibly();
// ....
l2.lockInterruptibly();
// Thread 2.
l2.lockInterruptibly();
// ....
l1.lockInterruptibly();
可重入意味着已经持有锁的单个线程可以重新获取锁 在您的例子中,有两个不同的线程正在创建 这称为重新进入锁定,类似于死锁和嵌套监视器锁定 您可以通过在线程t1中修复此问题
l1.lockInterruptibly();
System.out.println("I am in t1 step 1 " + o1.toString());
Thread.sleep(1000);
l2.lockInterruptibly();
在线程t2中
l2.lockInterruptibly();
System.out.println("I am in t2 step 1 " + o2.toString());
Thread.sleep(1000);
l1.lockInterruptibly();
可重入意味着已经持有锁的单个线程可以重新获取锁 在您的例子中,有两个不同的线程正在创建 这称为重新进入锁定,类似于死锁和嵌套监视器锁定 您可以通过在线程t1中修复此问题
l1.lockInterruptibly();
System.out.println("I am in t1 step 1 " + o1.toString());
Thread.sleep(1000);
l2.lockInterruptibly();
在线程t2中
l2.lockInterruptibly();
System.out.println("I am in t2 step 1 " + o2.toString());
Thread.sleep(1000);
l1.lockInterruptibly();
它不会引发中断异常,有人能告诉我为什么吗
public class Test {
public static void main(String[] args) throws InterruptedException {
final Object o1 = new Object();
final Object o2 = new Object();
final ReentrantLock l1 = new ReentrantLock();
final ReentrantLock l2 = new ReentrantLock();
Thread t1 = new Thread() {
public void run() {
try {
l1.lockInterruptibly();
System.out.println("I am in t1 step 1 " + o1.toString());
Thread.sleep(1000);
l2.lock();
try {
System.out.println("I am in t1 step 2 " + o2.toString());
} finally {
l2.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
l2.lockInterruptibly();
System.out.println("I am in t2 step 1 " + o2.toString());
Thread.sleep(1000);
l1.lock();
try {
System.out.println("I am in t2 step 2 " + o1.toString());
} finally {
l1.unlock();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}
可能是因为创建ReentrantLock的目的是互斥
每当程序中的线程将互斥锁保持超过一小部分秒时,这就是一种糟糕的代码气味
使lock.lock()
调用可中断将使所有使用它的程序复杂化:在每个要锁定锁的地方,都必须为InterruptedException
编写一个处理程序
我的猜测(仅此而已)是,作者认为他们不应该让所有程序员都必须编写这些额外的中断处理程序,这样一些程序员就可以在糟糕的设计中使用ReentrantLock
它不会引发中断异常,有人能告诉我为什么吗
public class Test {
public static void main(String[] args) throws InterruptedException {
final Object o1 = new Object();
final Object o2 = new Object();
final ReentrantLock l1 = new ReentrantLock();
final ReentrantLock l2 = new ReentrantLock();
Thread t1 = new Thread() {
public void run() {
try {
l1.lockInterruptibly();
System.out.println("I am in t1 step 1 " + o1.toString());
Thread.sleep(1000);
l2.lock();
try {
System.out.println("I am in t1 step 2 " + o2.toString());
} finally {
l2.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
l2.lockInterruptibly();
System.out.println("I am in t2 step 1 " + o2.toString());
Thread.sleep(1000);
l1.lock();
try {
System.out.println("I am in t2 step 2 " + o1.toString());
} finally {
l1.unlock();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}
可能是因为创建ReentrantLock的目的是互斥
每当程序中的线程将互斥锁保持超过一小部分秒时,这就是一种糟糕的代码气味
使lock.lock()
调用可中断将使所有使用它的程序复杂化:在每个要锁定锁的地方,都必须为InterruptedException
编写一个处理程序
我的猜测(仅此而已)作者认为他们不应该让所有的程序员都编写那些额外的中断处理程序,只是为了让一些程序员在糟糕的设计中使用
ReentrantLock
。我认为竞争
应该是竞争条件
…我认为竞争
应该是竞争条件
…谢谢你:-),你是对的,我必须在为每个线程使用第二个锁时使用可中断锁定。谢谢:-),你是对的,我必须在为每个线程使用第二个锁时使用可中断锁定。