FutureTask中的putOrderedInt怎么理解?

https://www.zhihu.com/question/394805625

问题:

查看FutureTask源码:

protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

设置结果的时候,通过putOrderedInt设置state字段。

private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // cannot time out yet
                //通过Thread.yield()等待
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
    }

获取结果时,如果发现state为COMPLETING,则通过Thread.yeild()让出cpu时间的方式,等待结果完成。

问题:

putOrderedInt,按网上的说法是保证了putOrderedInt以及之前的写不被重排序,但不保证数据被刷新到主存。

那么,get()的时候,怎么保证能够看到state状态变为NORMAL状态呢?

如果看不到state的变化,get()方法就会一直等待下去了。

求解答是什么保证了get()一定能看到state变为最终状态。

回答:

说下我的理解:

putOrderedInt保证写不被重排序,但不强制将store buffer里的数据刷新到内存,也就是说别的线程读state时可能不会立马就能看到state的更新,存在一定延迟性。如果正巧一个线程putOrderedInt完,另一个线程立马要读这个state,没读到更新,主动yield,这样会浪费一点cpu,并发生线程切换的资源消耗。

FutureTask的作者应该是认为,这种低概率下产生的成本消耗要优于每次写都要强刷store buffer的固定成本消耗。这就是state被定义为volatile类型变量,这里却没有选择直接使用state=value的赋值形式的原因吧。

魔鬼藏在细节里,作者对并发编程的掌控真的绝了。可惜的是对于我们大部分人来说,连并发编程的实践机会都没有,最多可能就用个线程池完了。



 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值