我正在尝试实现死锁条件,但不知怎的,我无法让它工作。线程Thread1和Thread2都进入run函数,但只有一个进入Sub / Sum,具体取决于谁先输入run。示例:如果首先运行Thread2,它将调用sub(),而Thread1从不调用sum()。我还添加了睡眠时间,以便Thread2在调用sum()之前休眠,并且Thread1有足够的时间输入Sum()但Thread1永远不会进入。
public class ExploringThreads {
public static void main(String[] args) {
// TODO Auto-generated method stub
threadexample a1 = new threadexample();
Thread t1 = new Thread(a1, "Thread1");
Thread t2 = new Thread(a1,"Thread2");
t1.start();
t2.start();
}
}
class threadexample implements Runnable{
public int a = 10;
public void run(){
if(Thread.currentThread().getName().equals("Thread1"))
sum();
else if(Thread.currentThread().getName().equals("Thread2"))
sub();
}
public synchronized void sum()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sum");
sub();
}
public synchronized void sub()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sub");
sum();
}
}
答案 0 :(得分:1)
这不是你如何陷入僵局。实际上这段代码似乎很安全:-)一次只有一个线程输入sum / sub,因为你使用的是synchronized,它在“this”上同步。只有一个“这个”,所以两个线程都试图获得相同的锁。
例如,当Thread1有一个锁,Thread2有第二个锁,然后Thread1想要获取Thread2的锁同时仍然保持它的锁定而Thread2想要获取Thread1的锁同时仍然保持锁定时,会发生死锁。
>你能做的是:
a)在“threadexample”类中添加2个对象以锁定(按惯例,btw类应以大写字母开头):
private final Object sumLock = new Object();
private final Object subLock = new Object();
b)在sum / sub方法中删除“synchronized”关键字,而是在每个方法中使用synchronized(){}块。 Sum将被同步(sumLock){/ * sum的主体在这里 /}并且sub将被同步(subLock){/ sub的主体在这里* /}。
在这种情况下,Thread1将进入sum(),获取sumLock并等待。 Thread2将进入sub(),获取subLock()并等待。 Thread1会被唤醒,进入sub()并尝试获取subLock但它被Thread2保留,所以它等待直到Thread2释放它。在那个时候,Thread2被唤醒,进入sum()并尝试获取由Thread1持有的sumLock,以便Thread2等待Thread1释放它。
任何一个线程都不会前进,因为每个线程都在等待另一个 - 你有一个死锁。
@Edit:是的,你只有1个“threadexample”实例,并且Thread1和Thread2都在争夺锁定,但当其中一个获得锁定时,它会在执行sum / sub或sub / sum后释放它。例如,假设Thread1是第一个并开始执行sum()。它有锁。在这种情况下,Thread2不会进入sub(),因为它受与Thread1相同的锁保护。 Thread1将执行sum(),然后执行sub(),然后它将释放锁定 - > Thread2将进入sub()等。
答案 1 :(得分:1)
如果你真的想创造一个人工死锁,试试这个:
Thread1
和Thread2
是两个想要访问同一文件的线程。
Thread1
启动,要求锁定File1.docx
并睡眠2分钟。 Thread2
启动,并对File2.docx
进行独占锁定,现在想要访问File1.docx
。 Thread1
醒来,现在想要访问由File2.docx
Thread2
醇>
现在,这是一个循环等待条件
简单吗? =)
答案 2 :(得分:0)
这是“行动中的死锁”的一个有效例子。基本上你需要做的事情(以及现实世界中通常会发生的事情)是对象被锁定的顺序相反:一个线程中的第一个,第二个,第一个是b,第二个是第二个:
package stackoverflow;
public class Deadlock {
final static String a = new String("A");
final static String b = new String("B");
public static void main(String[] args) {
final Thread abLock = new Thread() {
@Override
public void run() {
lock(a, b);
}
};
final Thread baLock = new Thread() {
@Override
public void run() {
lock(b, a);
}
};
abLock.start();
baLock.start();
}
static void lock(String first, String second) {
synchronized (first) {
System.out.println(first);
sleep();
synchronized (second) {
System.out.println(second);
}
}
}
static void sleep() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}