简体   繁体   English

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

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

i am reading sourcecode to figure out how bias lock works.我正在阅读源代码以了解偏置锁定的工作原理。 i have a question about "bulk rebias", which occured when the number of revocation of a particular data type instances.我有一个关于“批量重新偏置”的问题,这是在撤销特定数据类型实例的数量时发生的。 and this would increase epoch field in klass to invalidates previously held biases facilitates the bulk transfer of bias ownership from one thread to another.这将增加klass 中的 epoch 字段以使先前持有的偏见无效,从而有助于将偏见所有权从一个线程批量转移到另一个线程。

and this code follows, it was written in file biasedLocking.cpp :此代码如下,它是在文件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));
        }
      }
    }

the sourcecode is here .源代码在这里 it looks like to find all lock record which locked object's class equal to current obj's class and still biasable.它看起来像是找到所有锁定对象的类等于当前 obj 的类并且仍然有偏差的锁定记录。 if any lock record exist, its owner (lock object) must be locked with light-weight lock (thin lock) by a thread which means it should have has used bias lock and revoked by current owner, so why those code can find a lock object use bias pattern but locked with thin lock already?如果任何锁记录存在,它的所有者(锁对象)必须被一个线程用轻量级锁(薄锁)锁定,这意味着它应该使用偏向锁并被当前所有者撤销,那么为什么这些代码可以找到锁对象使用偏置模式但已经用细锁锁定了?

updated at 2020/04/02更新于 2020/04/02

i write some code to test:我写了一些代码来测试:

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() {
    }
}

} }

what i see via hsdb:我通过 hsdb 看到的:

在此处输入图片说明

em... main thread just exit monitor, and no contention it would use bias lock certainly. em...主线程只是退出监视器,没有争用它肯定会使用偏置锁。 why there are basicObjectMonitor on its stack?为什么它的堆栈上有 basicObjectMonitor ?

my jvm option我的 jvm 选项

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

my jdk version : 11.0.6我的 jdk 版本:11.0.6

first:MonitorObjectLock will allocated on current frame,whatever lock type the lock object use.第一:MonitorObjectLock 会在当前帧上分配,不管锁对象使用什么锁类型。 when monitor exit, biased lock released , lock oject's markword would not change, and the owning thread's stack keeps MonitorObjectLock and its obj field is NULL.当monitor退出时,biased lock被释放,锁对象的markword不会改变,拥有线程的栈保持MonitorObjectLock,其obj字段为NULL。 So "bulk rebias" will rebias MonitorObjectLock on stack when thread owned another biased-lock(not release and obj is not null and it is biasable) tries to own a biased but not owened lock and revocation count reach BiasedLockingBulkRebiasThreshold .因此,当线程拥有另一个偏向锁(不释放且 obj 不为空且它是可偏向的)尝试拥有偏向但未欠的锁并且撤销计数达到BiasedLockingBulkRebiasThreshold时,“批量重新偏向”将在堆栈上重新偏向 MonitorObjectLock 。

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

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