CAS和非阻塞计数器

时间:2010-11-18 22:59:16

标签: java concurrency

我一直在读Brian Goetz的JCIP。他解释了使用CAS指令实现非阻塞计数器。我无法理解如何使用CAS指令进行增量。任何人都可以帮我理解这一点。

public class CasCounter {
    private SimulatedCAS value;

    public int getValue() {
        return value.get();
    }

    public int increment() {
        int v;
        do {
            v = value.get();
        }
        while (v != value.compareAndSwap(v, v + 1));
        return v + 1;
    }
}

2 个答案:

答案 0 :(得分:4)

除了整个块都是原子块之外,

value.compareAndSwap(v, v + 1)等效于以下内容:(有关详细信息,请参阅compare-and-swap

int old = value.val;
if (old == v) {
  value.val = v + 1;
}
return old;

现在v = value.get()获取计数器的当前值,如果没有其他人同时尝试更新计数器,old == v将为真,因此该值设置为{{1 (即递增)并返回v+1。循环从old开始终止。

假设其他人在我们v == old之后递增了计数器,那么v = value.get()将为false,并且该方法将立即返回old == v,这是更新后的值。从old开始,循环继续。

答案 1 :(得分:3)

compareAndSwap()方法将以原子方式执行以下操作:

- determine if `value` is equal to `v`
- if so, it will set `value` to `v+1`
- it returns whatever `value` was when the method was entered (whether or not `value` was updated)

调用者可以检查value是否是他们在被叫compareAndSwap()时所期望的内容。如果是,则调用者知道它已被更新。如果它不是预期的那样,调用者知道它没有被更新,并将再次尝试,使用value的“新”当前值作为预期(这就是循环正在做的事情)。 / p>

这样,调用者可以知道增量操作不会被尝试同时修改value的其他线程丢失。