首页 文章

模拟Java线程死锁

提问于
浏览
2

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

例如,我有一个 class

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'并且两个同步实例方法无法同时运行,这些事情使得我们无法模拟死锁 . 我对么?

2 回答

  • 2

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

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

    因此,如果线程A已经在执行同步实例方法(在 this 上有锁)并尝试进入其中一个同步静态方法,而另一个线程B也已经在执行静态方法(在 MyClass.class 上锁定)并且现在尝试输入同步实例方法 on the same 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

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

    我想我不知道你的任务中允许什么,这有点令人困惑 .

相关问题