繁体   English   中英

为什么锁定对象使用偏置模式但已经用细锁锁定

[英]why lock object use bias pattern but but locked with thin lock already

我正在阅读源代码以了解偏置锁定的工作原理。 我有一个关于“批量重新偏置”的问题,这是在撤销特定数据类型实例的数量时发生的。 这将增加klass 中的 epoch 字段以使先前持有的偏见无效,从而有助于将偏见所有权从一个线程批量转移到另一个线程。

此代码如下,它是在文件biasedLocking.cpp中编写的:

for (; JavaThread *thr = jtiwh.next(); ) {
      GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
      for (int i = 0; i < cached_monitor_info->length(); i++) {
        MonitorInfo* mon_info = cached_monitor_info->at(i);
        oop owner = mon_info->owner();
        markOop mark = owner->mark();
        if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
          // We might have encountered this object already in the case of recursive locking
          assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
          owner->set_mark(mark->set_bias_epoch(cur_epoch));
        }
      }
    }

源代码在这里 它看起来像是找到所有锁定对象的类等于当前 obj 的类并且仍然有偏差的锁定记录。 如果任何锁记录存在,它的所有者(锁对象)必须被一个线程用轻量级锁(薄锁)锁定,这意味着它应该使用偏向锁并被当前所有者撤销,那么为什么这些代码可以找到锁对象使用偏置模式但已经用细锁锁定了?

更新于 2020/04/02

我写了一些代码来测试:

package tech.lovelycheng.learning.javalang.jvmtest;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.*;

import static java.lang.System.err;

public class BIASREVOKEDANDREBIASEDTest {

private static final Unsafe U;
private static final long OFFSET = 0L;

static {

    try {
        Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
        unsafe.setAccessible(true);
        U = (Unsafe) unsafe.get(null);
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
}

public static void main(String[] args) throws ExecutionException, InterruptedException {
    ExecutorService threadPoolExecutor = Executors.newSingleThreadExecutor();

    Monitor monitor = new Monitor();

    synchronized (monitor) {

        err.println("monitor header: " + printBinaryHeader(monitor));
        //reach biasedLockingBulkRebiasThreshold
        for (int i = 0; i < 5; i++) { // to bulk rebias
            Monitor s = new Monitor();

            synchronized (s) {

            }

            threadPoolExecutor.submit(() -> {
                synchronized (s) {

                }
                return null;
            }).get();
        }
    }

    err.println("monitor header: " + printBinaryHeader(monitor));// break point here

    ss(threadPoolExecutor, monitor);


    threadPoolExecutor.shutdown();


}

private static void ss(ExecutorService threadPoolExecutor, Monitor monitor) throws InterruptedException, ExecutionException {
    threadPoolExecutor.submit(() -> {
        synchronized (monitor) {
            err.println("expect 101 at low end  monitor header: " + printBinaryHeader(monitor));
        }
    }).get();
}

private static String printHeader(Object a) {
    int word = U.getInt(a, OFFSET);
    return Integer.toHexString(word);
}

private static String printBinaryHeader(Object a) {
    int word = U.getInt(a, OFFSET);
    return Integer.toBinaryString(word);
}


private static class Monitor {
    // mutex object

    public void fn() {
    }
}

}

我通过 hsdb 看到的:

在此处输入图片说明

em...主线程只是退出监视器,没有争用它肯定会使用偏置锁。 为什么它的堆栈上有 basicObjectMonitor ?

我的 jvm 选项

-XX:+UseBiasedLocking
-XX:BiasedLockingStartupDelay=0
-Xlog:biasedlocking=trace
-XX:BiasedLockingBulkRebiasThreshold=5
-XX:BiasedLockingBulkRevokeThreshold=20
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1

我的 jdk 版本:11.0.6

第一:MonitorObjectLock 会在当前帧上分配,不管锁对象使用什么锁类型。 当monitor退出时,biased lock被释放,锁对象的markword不会改变,拥有线程的栈保持MonitorObjectLock,其obj字段为NULL。 因此,当线程拥有另一个偏向锁(不释放且 obj 不为空且它是可偏向的)尝试拥有偏向但未欠的锁并且撤销计数达到BiasedLockingBulkRebiasThreshold时,“批量重新偏向”将在堆栈上重新偏向 MonitorObjectLock 。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM