模拟Java线程死锁

时间:2015-02-19 03:24:11

标签: java multithreading

是否可以在多个线程之间共享一个对象来模拟Java死锁场景?

例如我有一个班级

public class MyClass {

    public synchronized void syncInstanceMethod1(){
        /// Anything here to simulate a dead lock

    }
    public synchronized void syncInstanceMethod2(){
        /// Anything here to simulate a dead lock
    }
    public static synchronized void syncStaticMethod1(){
        /// Anything here to simulate a dead lock
    }
    public static synchronized void syncStaticMethod2(){
        /// Anything here to simulate a dead lock
    }

    public void instanceMethod1(){
        /// Anything here to simulate a dead lock
    }

    public void instanceMethod2(){
        /// Anything here to simulate a dead lock
    }


    public static void main(String[] args) {
        MyClass shared = new MyClass();  // Allowed to create only one instance

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {

                // Do whatever here to simulate dead lock like calling various methods on the shared object in any order

            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {

                // Do whatever here to simulate dead lock like calling various methods on the shared object in any order

            }
        });

        // Allowed to create more threads like above. t3 , t4 etc...

       t1.start();
       t2.start();
    }

}

可能是不可能的。由于可能发生死锁的常见情况是代码块,它获取锁定一个对象而不释放它尝试获取另一个对象的锁定。

我们可以通过调用静态同步方法从同步实例方法之一模拟这种情况,即尝试锁定'类'同时按住锁定对象'这个'。但是为了发生僵局,我们需要在其他地方以相反的顺序出现类似的情况。

另外,由于静态方法无法访问这个'它无法锁定这个'而且两个同步的实例方法不能同时运行,这些东西让人相信我们无法在这里模拟死锁。我是对的吗?

2 个答案:

答案 0 :(得分:2)

虽然您已被要求仅创建一个实例,但线程仍有两个锁可以争用。实例方法需要一个线程来获取MyClass对象实例上的锁,即sharedthis,具体取决于您的查看方式。

另一方面,静态方法需要一个线程来获取MyClass.class 对象实例上的锁;你从this.getClass()得到的那个。

因此,如果线程A已经在执行同步实例方法(对this具有锁定)并尝试进入其中一个同步静态方法,而另一个线程B也已经在执行静态方法(锁定MyClass.class),现在尝试在同一个 MyClass对象上输入同步实例方法,将发生死锁。

这是一些模拟此场景的代码。

public class SingleObjectDeadlock {

    public synchronized void syncInstanceMethod1() {
        System.out.println("In syncInstanceMethod1()");
        syncStaticMethod2();
    }

    public synchronized void syncInstanceMethod2() {
        System.out.println("In syncInstanceMethod2()");
    }

    public static synchronized void syncStaticMethod1(SingleObjectDeadlock shared) {
        System.out.println("In syncStaticMethod1()");
        shared.syncInstanceMethod2();
    }

    public static synchronized void syncStaticMethod2() {
        System.out.println("In syncStaticMethod2()");
    }

    public static void main(String[] args) {
        SingleObjectDeadlock shared = new SingleObjectDeadlock();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                shared.syncInstanceMethod1();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                SingleObjectDeadlock.syncStaticMethod1(shared);
            }
        });

        t1.start();
        t2.start();

        System.out.println("DEADLOCK!");
    }
}

运行后,您会发现死锁并且程序永远不会打印

In syncStaticMethod2()
In syncInstanceMethod2()

答案 1 :(得分:1)

我第一次阅读时误解了你的问题。但是如果共享实例不在静态同步方法的范围内(比如带有静态变量的引用),那么您将无法先在静态上锁定,然后在共享实例上锁定,因为它&# 39;不在范围内,不能锁定或调用它。

我想我不知道你的作业中允许了什么,这有点令人困惑。