Ala*_*lan 6 java concurrency lock-free
我使用AtomicReference来实现AtomicInteger.然而,在测试中,我注意到即使在单线程环境中,一旦其值达到128,CAS操作就会卡住.我做错了什么或在AtomicReference中有一个警告(可能与CPU有关)?这是我的代码:
public class MyAtomInt {
private final AtomicReference<Integer> ref;
public MyAtomInt(int init) {
ref = new AtomicReference<Integer>(init);
}
public MyAtomInt() {
this(0);
}
public void inc() {
while (true) {
int oldVal = ref.get();
int nextVal = oldVal + 1;
boolean success = ref.compareAndSet(oldVal, nextVal); // false once oldVal = 128
if (success) {
return;
}
}
}
public int get() {
return ref.get();
}
static class Task implements Runnable {
private final MyAtomInt myAtomInt;
private final int incCount;
public Task(MyAtomInt myAtomInt, int cnt) {
this.myAtomInt = myAtomInt;
this.incCount = cnt;
}
@Override
public void run() {
for (int i = 0; i < incCount; ++i) {
myAtomInt.inc();
}
}
}
public static void main(String[] args) throws Exception {
MyAtomInt myAtomInt = new MyAtomInt();
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(new Task(new MyAtomInt(), 150)).get();
System.out.println(myAtomInt.get());
exec.shutdown();
}
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*bel 10
这样做的原因是当你int打入一个Integer,你可能会或可能不会创建一个新的Integer实例.如果这样做,则新实例可能与其他Integer实例没有引用相等,即使它们共享相同的值. AtomicReference.compareAndSet()使用引用相等(标识)进行比较.
关键在于编译器如何处理int值的自动装箱:它会发出调用Integer.valueOf().作为优化,Integer.valueOf()具有盒装整数的缓存,并且默认情况下该缓存包括最多128的值.如果您将整数包装n两次,Integer如果该值足够小以便在缓存中,则每次都会得到相同的引用; 否则,您将获得两个单独的实例.
目前,您取消装入旧值,计算新值,并在您打电话时再次装入compareAndSet()旧值.一旦达到128,就会停止获取缓存值,因此第二个盒装副本不再与中的相同.AtomicReference
| 归档时间: |
|
| 查看次数: |
256 次 |
| 最近记录: |