Java “是什么意思?”;“可重入锁定”;在爪哇?

Java “是什么意思?”;“可重入锁定”;在爪哇?,java,reentrancy,Java,Reentrancy,可重入性意味着锁是在每个线程而不是每次调用的基础上获取的 由于内在锁由线程持有,这难道不意味着线程运行一次就等于调用基础吗 谢谢,这似乎意味着:在一个线程中,如果我在处理调用函数doB的函数doA时得到一个锁lockA,并且doB也需要一个锁lockA,那么将有一个重入。在爪哇,这种现象是通过线程获取的,所以我不需要考虑死锁(),这意味着线程一旦有了锁,它就可以按需要进入代码的锁定部分。因此,如果您有一段同步的代码,比如一个方法,那么只有获得锁的线程才能调用该方法,但可以根据需要多次调用该方法,

可重入性意味着锁是在每个线程而不是每次调用的基础上获取的

由于内在锁由线程持有,这难道不意味着线程运行一次就等于调用基础吗


谢谢,这似乎意味着:在一个线程中,如果我在处理调用函数
doB
的函数
doA
时得到一个锁
lockA
,并且
doB
也需要一个锁
lockA
,那么将有一个重入。在爪哇,这种现象是通过线程获取的,所以我不需要考虑死锁(

),这意味着线程一旦有了锁,它就可以按需要进入代码的锁定部分。因此,如果您有一段同步的代码,比如一个方法,那么只有获得锁的线程才能调用该方法,但可以根据需要多次调用该方法,包括由同一个锁持有的任何其他代码。如果有一个方法调用另一个方法,并且两个方法都由同一个锁同步,那么这一点很重要。如果不是这样的话。第二个方法调用将阻塞。它也适用于递归方法调用

public void methodA()
{
     // other code
     synchronized(this)
     {
          methodB();
     } 
}

public void methodB()
{
     // other code
     syncrhonized(this)
     {
          // it can still enter this code    
     }

}
可重入性意味着锁是在每个线程而不是每次调用的基础上获取的

这是一个误导性的定义。这是真的(有点),但它没有抓住要点

重入意味着(在一般的CS/IT术语中)你做了一些事情,当你还在做的时候,你又做了一次。在锁的情况下,这意味着您可以在单个线程上执行以下操作:

  • 获取“foo”上的锁
  • 做点什么
  • 获取“foo”上的锁。请注意,我们尚未释放之前获得的锁
  • 释放“foo”上的锁
  • 释放“foo”上的锁
  • 使用可重入锁/锁定机制,获取相同锁的尝试将成功,并将增加属于锁的内部计数器。只有当前的锁持有人已释放两次锁时,才会释放锁

    下面是一个使用基本对象锁/监视器的Java示例。。。哪些是可重入的:

    Object lock = new Object();
    ...
    synchronized (lock) {
        ...
        doSomething(lock, ...)
        ...
    }
    
    public void doSomething(Object lock, ...) {
        synchronized (lock) {
            ...
        }
    }
    
    可重入的替代方法是非可重入锁定,线程尝试获取其已持有的锁将是一个错误

    使用可重入锁的优点是,您不必担心由于意外获取已持有的锁而失败的可能性。缺点是你不能假设你调用的任何东西都不会改变锁用来保护的变量的状态。然而,这通常不是问题。锁通常用于防止其他线程同时更改状态


    所以我不需要考虑死锁?< /P> 是的,你知道


    线程不会针对自身死锁(如果锁是可重入的)。但是,如果有其他线程可能锁定了您试图锁定的对象,则可能会出现死锁。

    想象一下这样的情况:

    function A():
       lock (X)
           B()
       unlock (X)
    
    function B():
        A()
    
    现在我们称之为A。发生以下情况:

    • 我们输入A,锁定X
    • 我们进入B
    • 我们再次输入A,再次锁定X
    因为我们从未退出对A的第一次调用,所以X仍然被锁定。这被称为重新进入-当函数A还没有返回时,函数A被再次调用。如果依赖于某个全局静态状态,这可能会导致“重新进入错误”,在从函数的退出清除静态状态之前,函数将再次运行,并且一半的计算值与第二次调用的开始发生冲突

    在这种情况下,我们遇到了一个我们已经持有的锁。如果锁是可重新进入的,它将意识到我们是同一条已经持有锁的线程,并让我们通过。否则,它将永远死锁——它将等待它已经拥有的锁


    在java中,
    lock
    synchronized
    是可重新进入的-如果锁由线程持有,并且线程尝试重新获取相同的锁,则允许重新进入。因此,如果我们用Java编写上述伪代码,它就不会死锁。

    实践书中的Java并发状态-
    重入意味着锁是在每个线程而不是每次调用的基础上获取的。

    让我解释一下它的确切含义。首先,内在锁本质上是可重入的。实现可重入性的方法是为获取的锁的数量和锁的所有者维护一个计数器。如果计数为0且没有所有者与之关联,则表示锁不由任何线程持有。当线程获取锁时,JVM记录所有者并将计数器设置为1。如果同一线程再次尝试获取锁,则计数器将递增。当所属线程退出同步块时,计数器将递减。当计数再次达到0时,锁被释放

    一个简单的例子是——

    public class Test {
        public synchronized void performTest() {
           //...
        }
    }
    
    public class CustomTest extends Test {
        public synchronized void performTest() {
           //...
           super.performTest();
        }
    }
    
    如果没有重新进入,就会出现僵局

    可重入性意味着锁是在每个线程而不是每次调用的基础上获取的

    让我用一个例子来解释这一点

    class ReentrantTester {
    
        public synchronized void methodA() {
          System.out.println("Now I am inside methodA()");
          methodB();
        }
    
        public synchronized void methodB() {
          System.out.println("Now I am inside methodB()");
        }
    
        public static void main(String [] args) {
            ReentrantTester rt = new ReentrantTester();
            rt.methodA();  
        }
    
    }
    
    结果是:

    Now I am inside methodA()
    Now I am inside methodB()
    
    与上面的代码一样,ReentrantTester包含两个同步的方法:methodA()&methodB() 第一个同步方法methodA()调用另一个同步方法methodB()

    当执行进入methodA()时,当前线程获取ReentrantTester对象的监视器。 现在,当methodA()调用methodB()时,因为methodB()也是同步的,所以线程尝试获取 还是同一个监视器。因为Java支持可重入监视器,所以这是可行的。当前线程获取可重入测试程序的 再次监视并继续执行methodA()和methodB()

    Java运行时允许线程重新获取它已经持有的监视器,因为Java监视器是 可重入的。这些可重入监视器非常重要,因为它们消除了单个线程的可能性 死亡的
    private lock = new ReentrantLock();
    public void method() {
          lock.lock();
          method();
    }