美文网首页程序员Java
从happen-before角度分析synchronized与l

从happen-before角度分析synchronized与l

作者: yuan_dongj | 来源:发表于2019-12-27 22:51 被阅读0次

    充电时刻(happen-before八个原则)


    • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
    • 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
    • volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
    • 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

    • start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
    • Join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
    • 程序中断规则:对线程interrupted()方法的调用先行于被中断线程的代码检测到中断时间的发生。
    • 对象finalize规则:一个对象的初始化完成(构造函数执行结束)先行于发生它的finalize()方法的开始。

    推荐阅读: java 8大happen-before原则超全面详解

    happen-before不能理解成在什么之前发生,它和时间没有任何关系,解释成“生效可见于” 更准确。即使出现了指令重排,只要符合happen-before规则,那么上文的结果就会对下文生效。

    关于内存可见性的疑惑

    一个简单的例子

        private static int count;
    
        public void incr() {
            //加锁
            while(count <= 100) {
                count++;
            }
            //解锁
        }
    

    不知道大家有没有像我一样的疑惑,无论是使用哪种加锁方式,count变量并没有被volatile修饰,那么对count变量的修改是如何保证内存可见性的呢?

    好像对这件事是如此的理所应当,就像太阳每天从东方升起,不觉得这有什么好质疑的。

    lock的内存可见性

    以ReentrantLock公平锁为例,我们看看获取锁 & 释放锁的关键代码

        private volatile int state;
    
        protected final int getState() {
            return state;
        }
    
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            //重要
            int c = getState(); //line 1
            //...竞争锁逻辑忽略
        }
    
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            // ...根据状态判断是否成功释放,省略
    
            //写volatile变量,重要
            setState(c); // line 2
            return free;
        }
    

    假设有A,B两个线程执行count++,A线程抢到执行权,B线程阻塞。A线程释放锁时会走line 2,这时B线程继续争抢执行权执行line 1。

    • 对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

      A线程释放锁setState一定生效可见于B线程获取锁getState

    • 一个线程中的每个操作,happens-before于该线程中的任意后续操作。

      A线程的count++一定生效可见于A线程解锁

    • 如果A happens-before B,且B happens-before C,那么A happens-before C。

      A线程的count++一定生效可见于B线程获取锁getState以及后续的业务处理

    synchronized的内存可见性

    • 对一个锁的解锁,happens-before于随后对这个锁的加锁。

      A线程的解锁一定生效可见于B线程获取锁,后续流程分析与lock一致。

    相关文章

      网友评论

        本文标题:从happen-before角度分析synchronized与l

        本文链接:https://www.haomeiwen.com/subject/drsjoctx.html