【问题标题】:two threads entering the two different synchrnozied method at same time on instance level lock两个线程在实例级锁上同时进入两个不同的同步方法
【发布时间】:2017-05-03 12:19:12
【问题描述】:

我在一次采访中被问到关于多线程,假设你在同一个对象上有 2 个线程(Thread-1 和 Thread-2)。 Thread-1在同步的method1()中,Thread-2可以通过任何方式在java中同时进入同步的method2()。

我回答不 不,这里当 Thread-1 在同步方法 1() 中时,它必须在对象的监视器上保持锁定,并且只有当它退出同步方法 1() 时才会释放对象监视器上的锁定。因此,Thread-2 必须等待 Thread-1 释放对象监视器上的锁定,才能进入同步方法 2()。

但仍然请告知是否有任何方式 Thread-2 可以通过任何方式在 java 中同时输入同步的方法 2() 是否有任何黑客来实现这件事

下面是我的程序,现在仪式我已经改变了现在的实现,请就此提出建议,因为下面程序的输出是

inside M1()
t1--->RUNNABLE
inside M2()
t2--->RUNNABLE

下面是我更新的代码

public class Test {

     private final Object lockA = new Object();
     private final Object lockB = new Object();

    public  void m1() {
         synchronized(lockA) {
        try {
            System.out.println("inside M1()");
            Thread.sleep(100);         
        }
        catch (InterruptedException ie) 
        {}
         }
    }

    public  void m2() {
        synchronized(lockB) {
        try { 
            System.out.println("inside M2()");
            Thread.sleep(100); }
        catch (InterruptedException ie) {}
    }
    }

    public static void main(String[] args) throws InterruptedException {
        final Test t = new Test();
        Thread t1 = new Thread()
        { public void run() { t.m1(); } };
        Thread t2 = new Thread()
        { public void run() { t.m2(); } };

        t1.start();
        //Thread.sleep(500);

        t2.start();
      //  Thread.sleep(500);

        System.out.println("t1--->"+t1.getState());
        System.out.println("t2--->"+t2.getState());
    }
}

【问题讨论】:

标签: java multithreading


【解决方案1】:

请注意,在您的示例中,即使 MyRunnable1 类只有一个 method1() 并且您的 run() 函数在循环中调用此方法,线程也不会在任何事情上竞争。因为 thread1 和 thread2 是不同的实例,并且每个实例都有自己的 method1() 副本,所以 synchronized 使用的锁是不同的,而不是一个单独的锁。

【讨论】:

  • 我不同意你的观点,因为他使用单一可运行,它使用相同的锁。该方法也是共享的,没有其他副本。
  • 你是对的我没有注意到对不起我的错误
【解决方案2】:

两个线程不能同时持有同一个锁。然而,仅仅因为线程在对象的synchronized 方法中,并不意味着它持有锁。例如,它可以在条件变量上调用await 并在等待时释放锁。这允许其他线程通过输入synchronized 方法来获取锁——毕竟,这就是你在等待的。

【讨论】:

  • 这个帖子中唯一正确的答案,也是唯一一个投反对票的...
【解决方案3】:

你的代码如下:

void method1(){
      synchronized(this) {
           //...
      }
}

synchronized void method2(){
      synchronized(this) {
           //...
      }
}

并且在您的代码中,两个线程不能同时进入两个方法来进行锁竞争。您只能在不同的可运行实例上执行此操作,即不同的 this。

【讨论】:

  • 这是不正确的。请参阅我的答案——其中一个//... 可能包含释放锁并让另一个线程进入synchronized 块的代码。
  • @DavidSchwartz 我在他的旧代码示例中说,他不能这样做,除非使用不同的实例。 :)
【解决方案4】:

你的理解是正确的,每个对象都有与之关联的锁,一旦Thread1获得锁访问同步方法1,那么线程2就无法访问同步方法2。

现在,在特殊情况下,您总是可以做一个简单的 hack。想象一下 Thread1 有锁,并且正在访问同步方法 1。在 method1 内部,如果 Thread1 对变量调用 wait,则它会释放对象上的锁并进入等待状态。在这种情况下,Thread2 可以获取锁并进入同步方法 2。因此,两个线程都可以访问同一个 obj 上的不同同步方法。

P.S. 这只是一个例子,我不建议在同步块中再等待,这会导致不必要的复杂化。如果任何代码都必须这样做,那就意味着逻辑和设计存在缺陷。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 2016-08-15
    相关资源
    最近更新 更多