Java 在这种情况下,线程如何同时获得两个对象上的锁?

Java 在这种情况下,线程如何同时获得两个对象上的锁?,java,multithreading,synchronization,thread-synchronization,Java,Multithreading,Synchronization,Thread Synchronization,我可以从这段代码中理解,一旦线程进入该方法,它就会在inst1上获取锁,然后在inst2上获取锁,而不会释放inst1锁。我假设这两个对象都没有被其他线程锁定。 如果一个线程一次只能获得一个对象的锁,并且只能 当当前对象上的锁被释放时,如何拥有另一个锁 这段代码是否有效,或者更确切地说,它是否是我认为我在某处见过的有效代码 如果Type1和Type2是相同的呢 如果我们使方法同步,考虑到它驻留在 方法的参数类型以外的类 一,。如果一个线程一次只能获得一个对象上的锁,并且在当前对象上的锁被释放时只

我可以从这段代码中理解,一旦线程进入该方法,它就会在inst1上获取锁,然后在inst2上获取锁,而不会释放inst1锁。我假设这两个对象都没有被其他线程锁定。

  • 如果一个线程一次只能获得一个对象的锁,并且只能 当当前对象上的锁被释放时,如何拥有另一个锁 这段代码是否有效,或者更确切地说,它是否是我认为我在某处见过的有效代码
  • 如果Type1和Type2是相同的呢
  • 如果我们使方法同步,考虑到它驻留在 方法的参数类型以外的类
  • 一,。如果一个线程一次只能获得一个对象上的锁,并且在当前对象上的锁被释放时只能拥有另一个锁,那么这段代码怎么可能是有效的,或者更确切地说,它是我认为我在某处见过的有效代码

    它是一个有效的代码,锁不在方法所在的对象上,而是在
    inst1
    inst2
    上。此外,锁不在类上,而是针对每个对象

    二,。如果Type1和Type2是相同的呢

    同样,锁在对象上,而不是类上。如果inst1和inst2相同,那么线程只有一个锁,同一线程“重新进入”锁是有效的

    三,。如果我们使方法同步,考虑到它驻留在方法的参数类型以外的类中,会发生什么


    然后还有另一个锁,这次是在执行方法的对象(而不是类)上。

    如果每次需要在这两个对象上获得锁时,代码都是按相同的顺序进行的,那么代码就没有问题了

    例如,如果您有两种方法

    public void method(Type1 inst1, Type2 inst2) {
      synchronized(inst1) {
        synchronized(inst2) {
          //do something now
        }
      }
    }
    

    你有一个潜在的死锁问题,因为一个线程可以获得inst1上的锁并等待inst2的锁,而另一个线程拥有inst2上的锁并等待inst1上的锁。

    多亏了@morgano和@Nick Holt,我知道一个线程可以同时持有多个锁(不同的对象),或者多次在同一对象上(使用
    synchronized
    获得的锁是隐式可重入的)。

    可以肯定,该代码很可能导致死锁雷区

    锁定inst2的第二个线程(threa2)不一定要通过methodA运行,但可以在另一个过程中锁定对象inst2,并在methodA中的thread1之前锁定对象inst2,然后在释放inst2之前访问方法A并尝试锁定inst2。啊!呜呜!:(

    建议的解决方案:
    在methodA上同步,而不是在对象上同步,因为这将锁定methodA()中访问的所有资源 像这样


    public synchronized void methodA(){….}

    理论上,线程可以持有的锁的数量没有限制。使用
    synchronized
    获得的锁是隐式可重入的,因此
    inst1
    inst2
    引用同一对象没有问题。我假设这是某种作业(如果是,则应将其标记为)。它试图让您思考的是死锁-如果线程1调用此方法传递
    objA
    objB
    ,那么会发生什么情况,同时线程2调用它传递
    objB
    objA
    ,这是一个常用于解释死锁的代码。同意。但我已经阅读了一些文本正如我所记得的,一个线程一次只能锁定一个对象,并且不能在不释放的情况下获取不同对象的锁。这是我的疑问!如果每个线程一次只允许持有一个锁,那么就不会有死锁。你要么误解了你读到的内容,要么你读到的内容是错误的。仅仅因为有人如果一个线程可以一个接一个地锁定多个不同的对象而不释放任何对象,那么我认为它肯定可以多次锁定同一个对象。那么为什么会有一个重入锁定的概念被解释为某个大的子主题呢?我只谈论一个线程e、 我知道在多个线程的情况下,如果一个线程试图在另一个线程已经占用的对象上获得锁,可能会出现死锁情况。好的,但这不是我的疑问!我怀疑线程如何同时锁定两个对象。一个线程可以同时锁定多个对象吗?
    public void methodA(Type1 inst1, Type2 inst2) {
      synchronized(inst1) {
        synchronized(inst2) {
          //do something now
        }
      }
    }
    
    public void methodB(Type1 inst1, Type2 inst2) {
      //wrong
      synchronized(inst2) {
        synchronized(inst1) {
          //do something now
        }
      }
    }