【问题标题】:How does a second thread check and recheck the lock object of a class that is current used by the first thread?第二个线程如何检查和重新检查第一个线程当前使用的类的锁对象?
【发布时间】:2017-02-11 07:55:04
【问题描述】:

我对java中同步方法的理解,其中第一个线程获取锁对象,因此如果第二个线程检查它看到它正在使用并“等待”直到线程一个完成,然后将锁传回,而第二个线程可以获得锁并继续。只是学习,如果关闭/过度简化......这就是原因。

我的问题是第二个线程“等待”的内部机制是什么......它会继续轮询还是重新检查该锁,直到它只是看到它的空闲?如果是这种情况,这是否会影响一堆正在运行的线程而不是第一个/第二个示例?或者它更像是一种注册类型的机制,允许将第二个线程放入排序队列中,然后在锁定可用时得到通知?

只是好奇。谢谢!

【问题讨论】:

    标签: java multithreading synchronization thread-safety


    【解决方案1】:

    JVM 处理内在锁定的方式因地而异,诸如 JVM 供应商、服务器/客户端选项、活动线程、等待时间、队列大小等因素都会影响线程锁定行为。

    HotSpot JDK VM 的实现对于像我这样的普通外行来说会非常神秘,我将把它留在这里进行进一步调查:http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/runtime/synchronizer.cpp

    在不深入研究源代码的情况下,AFAIK 内在锁定会保留一组不拥有锁的等待线程。如果一个线程尝试获取但失败了,它就会被添加到这个集合中,并且可能会执行一些不同的操作:

    1. Spin,这里有很多算法。当自旋成功获取锁时,会通知第二个线程。
    2. 上下文切换,暂停线程并释放处理器。退出线程通知下一个服务员。
    3. 睡眠,暂停线程但保留处理器。同 2。

    线程将做什么通常由启发式或线程获取的任何类型的锁决定。该系统还可以将不同的方法组合在一起,例如在睡眠前旋转 N 次,然后进行上下文切换。这取决于系统。我可能对我提出的一些或全部观点有误,因为我找不到任何支持我所说的话的参考资料。

    老实说,锁定的内部实现对 Java 开发人员来说应该是无关紧要的。 JVM 的线程调度和锁定非常高效,研究这些算法的工程师非常聪明,他们花费数周、数月和数年的时间进行测试并确保实现提供最佳性能。这就是为什么最低级别的线程控制来自thread parking,任何更低级别的线程都需要 JNI 或其他语言。如果您正在实现自己的同步器,请考虑使用AbstractQueuedSynchronizerJDK source 有详细的文档记录,您将看到非内在锁和其他高级同步器(如 ReentrantLock)是如何工作的。

    编辑

    JVM的实现路径是这样的:

    1. runtime/synchronizer.cpp
    2. High level spin
    3. Call to park event
    4. 操作系统调用:
    5. 仅限 Linux:NPTL -> Futex syscall

    【讨论】:

      【解决方案2】:

      我的问题是第二个线程“等待”的内部机制是什么......它会继续轮询还是重新检查该锁,直到它只是看到它的空闲?

      在大多数情况下,这根本不是由 JVM 处理的,而是由操作系统中的线程层处理的。也就是说,线程肯定不是轮询的。当第二个线程遇到一个已经被锁定的锁时,它会停止运行并被放入与该锁关联的有序等待队列中。当锁被解锁时,等待队列中的第一个线程(如果有的话)被唤醒并移动到运行队列中。

      如果是这种情况,这是否会影响一组正在运行的线程而不是第一个/第二个示例?

      没有。队列可以很好地扩展到大量线程。

      或者它更像是一种注册类型的机制,允许将第二个线程放入排序队列中,然后在锁定可用时得到通知?

      没错。线程完全停止运行,解锁锁的线程是启动线程再次运行的线程(或某种主管线程)。

      【讨论】:

        猜你喜欢
        • 2021-10-26
        • 1970-01-01
        • 2016-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-18
        • 2022-12-03
        相关资源
        最近更新 更多