CodisLabs/jodis

jodis原子性问题

Closed this issue · 9 comments

for (;;) {
int current = nextIdx.get();
int next = current >= pools.size() - 1 ? 0 : current + 1;
if (nextIdx.compareAndSet(current, next)) {
return pools.get(next).pool.getResource();
}
}

这段源码存在原子性问题

啥问题?

@OverRide
public Jedis getResource() {
ImmutableList pools = this.pools;
if (pools.isEmpty()) {
throw new JedisException("Proxy list empty");
}

        for (;;) {
            int current = nextIdx.get();
            int next = current >= pools.size() - 1 ? 0 : current + 1;
            if (nextIdx.compareAndSet(current, next)) {
                return pools.get(next).pool.getResource();
            }
        }
    
}

这段代码存在原子性问题

应该改成下面这样
@OverRide
public Jedis getResource() {
ImmutableList pools = this.pools;
if (pools.isEmpty()) {
throw new JedisException("Proxy list empty");
}
synchronized (this.pools) {
for (;;) {
int current = nextIdx.get();
int next = current >= pools.size() - 1 ? 0 : current + 1;
if (nextIdx.compareAndSet(current, next)) {
return pools.get(next).pool.getResource();
}
}
}
}

你是实际遇到问题了?还是看代码看到这里觉得有问题?
那个pools是个ImmutableList,生成了就不会变了,每次更新列表的时候都是创建一个新的ImmutableList,不会改之前的。

看代码啊,pools是原子的,for 中的死循环不是原子操作啊

那个nextIdx是AtomicInteger啊,标准的CAS原子操作

current不是原子的啊

current是个局部变量啊,只有本线程能访问到。。。

我错了,囧