【问题标题】:Simulating Java thread dead lock模拟Java线程死锁
【发布时间】:2015-02-19 03:24:10
【问题描述】:

是否可以在多个线程之间共享一个对象来模拟 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();
    }

}

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

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

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

【问题讨论】:

  • 静态方法可以通过静态变量的形式访问this(类似于单例模式)。

标签: java multithreading


【解决方案1】:

尽管您被要求只创建一个实例,但线程仍有两个锁要争用。实例方法将需要一个线程来获取MyClass 对象实例上的锁,即sharedthis,具体取决于您如何看待它。

另一方面,静态方法需要线程获取MyClass.class 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()

【讨论】:

    【解决方案2】:

    当我第一次阅读您的问题时,我误读了它。但是,如果共享实例不在您的静态同步方法的范围内(例如带有静态变量的引用),那么您将无法先锁定静态然后再锁定共享实例,因为它不在范围内,可以'不要锁定或调用它。

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

    【讨论】:

    • 您是否建议更改同步静态方法的签名以接受 MyClass 实例(共享)作为参数?
    • @gipsy 我第一次读到你的问题时误读了它。但是,如果共享实例不在您的静态同步方法的范围内(例如带有静态变量的引用),那么您将无法先锁定静态然后再锁定共享实例,因为它不在范围内,可以不要锁定或调用它。我想我不知道你的作业允许什么,这有点令人困惑。
    • 您的回答为我指明了正确的解决方案。但我接受 Ravi Thapliyal 的回答,因为它会更多地帮助其他人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 2016-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多