简体   繁体   English

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

[英]How can a thread acquire lock on two objects simultaneously as in this case?

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

I can understand from this piece of code that once a thread enters the method, it acquires the lock on inst1, and then it acquires lock on inst2, without releasing inst1 lock.从这段代码中我可以理解,一旦线程进入方法,它会先获取inst1的锁,然后再获取inst2的锁,而不释放inst1的锁。 I assume that both of these objects are not locked by other thread.我假设这两个对象都没有被其他线程锁定。

  1. If a thread can acquire lock on only one object at once and can only own another lock when lock on current object has been released, how can this piece of code be valid, or rather, is it a valid code that I think I have seen somewhere?如果一个线程一次只能获得一个对象上的锁,并且在当前对象上的锁被释放时只能拥有另一个锁,那么这段代码怎么可能有效,或者更确切地说,它是我认为我见过的有效代码某处?
  2. And what if Type1 and Type2 are same?如果 Type1 和 Type2 相同呢?
  3. What happens if we make the method synchronized, considering it resides in a class other than the parameter types of the method?如果我们使方法同步,考虑到它驻留在方法的参数类型以外的类中,会发生什么?

1 . 1。 If a thread can acquire lock on only one object at once and can only own another lock when lock on current object has been released, how can this piece of code be valid, or rather, is it a valid code that I think I have seen somewhere? 如果一个线程一次只能获取一个对象的锁,而当释放当前对象的锁时只能拥有另一个锁,那么这段代码如何有效?或者,我认为这是一个有效的代码吗?某处?

It is a valid code, the locks are not on the object where the method resides, but on inst1 and inst2 . 它是一个有效代码时,锁是不是其中该方法所在的对象上,但在inst1inst2 Also, the lock is not on the class, but for every object 同样,锁不是在类上,而是在每个对象上

2 . 2。 And what if Type1 and Type2 are same? 如果Type1和Type2相同怎么办?

again, the locks are on the objects, not on the classes. 同样,锁在对象上,而不在类上。 if inst1 and inst2 are the same, then the thread has only one lock, it is valid for the same thread to "re-enter" the lock 如果inst1和inst2相同,则该线程只有一个锁,对于同一线程“重新输入”锁是有效的

3 . 3。 What happens if we make the method synchronized, considering it resides in a class other than the parameter types of the method? 如果我们考虑到方法位于方法的参数类型之外的其他类中而使该方法同步,会发生什么情况?

Then you have yet another lock, this time on the object (not the class) where the method is being executed. 然后,您还有另一个锁,这次是在执行方法的对象(不是类)上。

由于@morgano@Nick霍尔特 ,我明白, 一个线程可以保持在同一时间多个锁 (不同的对象),或相同的对象上多次(使用获得的锁synchronized是隐含地折返)。

There is no problem with your code in case every time you need to obtain lock on those two objects you do it in the same order. 如果您每次需要以相同的顺序锁定这两个对象,则代码没有问题。

For example, if you have two methods 例如,如果您有两种方法

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
    }
  }
}

You have a potential deadlock problem as a thread could obtain the lock on inst1 and wait for the lock of inst2, while another thread have the lock on inst2 and wait for lock on inst1. 您有潜在的死锁问题,因为线程可以获取inst1上的锁并等待inst2,而另一个线程具有inst2上的锁并等待inst1上的锁。

That code is very likely to result in a deadlock minefield, for sure. 肯定的是,该代码很可能会导致雷区陷入僵局。

The 2nd thread(threa2) that locks inst2 does not necessarily have to be running through methodA, but may lock object inst2 in another procedure, and does so before the thread1 in methodA, and then accesses method A and attempts to lock inst2, before releasing inst2. 锁定inst2的第二个线程(threa2)不一定必须通过方法A运行,而是可以在另一个过程中锁定对象inst2,并且在方法A中的线程1之前执行此操作,然后在释放之前访问方法A并尝试锁定inst2。 INST2。 ahhhhh! AHHHHH! boooom! boooom! :(. :(。

suggested solution : 建议的解决方案:
synchronize on methodA, and not on the objects , as that will lock all resources accessed in methodA() like so 与methodA同步,而不是在object上同步,因为那样将锁定在methodA()中访问的所有资源,如下所示

public synchronized void methodA () {....} 公共同步void methodA(){....}

Deadlocks happen when you acquire one lock inside another:当您在另一个锁中获取一个锁时会发生死锁:

lock OB1 {
   lock OB2 { ... }
}    

because one could attempt to lock on a pair (1,2) and anther (2,1) .因为人们可能会尝试锁定一对(1,2)和花药(2,1) There are possible more lengthy chains: (1,2) + (2,3) + (3,1) .可能有更长的链: (1,2) + (2,3) + (3,1)

You need to introduce order between locks to avoid deadlocks: Java synchronisation: atomically moving money across account pairs?您需要在锁之间引入顺序以避免死锁: Java 同步:跨帐户对原子地转移资金?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JVM如何确保只有一个线程可以获取对象的锁? - How does JVM make sure only one thread can acquire the lock of an object? 明确从线程获取锁 - Explicitly acquire a lock from a thread notifyAll之后2个线程如何获取锁? - How does 2 thread able to acquire lock after notifyAll? 如何通过钥匙获取锁 - How to acquire a lock by a key 似乎在具有相同锁的一个线程正在休眠时,另一个线程能够获得该锁? - How does it seem to appear that another thread is able to acquire the lock while one thread having the same lock is sleeping? 如果信号量锁获取/尝试获取失败,如何让 Java 线程执行不同的任务而不是阻塞? - How can I make a Java thread do a different task rather than block if a semaphore lock acquire/tryAcquire fails? 当其他线程正在执行此类的静态同步方法时,线程可以获取该类实例的锁吗? - Can a thread acquire a lock on a instance of a class,when other thread is executing a static synchronized method of this class? 为什么Thread.interrupt()不能中断试图获取锁的线程 - Why can't Thread.interrupt() interrupt a thread trying to acquire lock 线程无法获得锁定会发生什么? - What happens to a Thread that fails to acquire a lock? Java多线程获取锁不起作用 - java multi-thread acquire lock not working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM