怎么注册自己的网站,慈溪市网站开发,个人可以建设网站吗不备案,装潢设计培训像synchronized这种独占锁属于悲观锁#xff0c;它是在假设一定会发生冲突的#xff0c;那么加锁恰好有用#xff0c;除此之外#xff0c;还有乐观锁#xff0c;乐观锁的含义就是假设没有发生冲突#xff0c;那么我正好可以进行某项操作#xff0c;如果要是发生冲突呢它是在假设一定会发生冲突的那么加锁恰好有用除此之外还有乐观锁乐观锁的含义就是假设没有发生冲突那么我正好可以进行某项操作如果要是发生冲突呢那我就重试直到成功乐观锁最常见的就是CAS。 我们在读Concurrent包下的类的源码时发现无论是ReenterLock内部的AQS还是各种Atomic开头的原子类内部都应用到了CAS最常见的就是我们在并发编程时遇到的i这种情况。传统的方法肯定是在方法上加上synchronized关键字:public class Test {public volatile int i;public synchronized void add() {i;}
}
复制代码但是这种方法在性能上可能会差一点我们还可以使用AtomicInteger就可以保证i原子的了。 public class Test {public AtomicInteger i;public void add() {i.getAndIncrement();}
}复制代码CAS源码分析获取偏移量valueOffsetpublic native long objectFieldOffset(Field var1);通过这个方法可以知道偏移量从jdk底层源码中获取。static {try {valueOffset unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField(value));} catch (Exception ex) { throw new Error(ex); }
}复制代码然后再看看增加的方法public final int getAndAdd(int delta) {return unsafe.getAndAddInt(this, valueOffset, delta);
}复制代码public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 var4));return var5;
}复制代码我们看var5获取的是什么通过调用unsafe的getIntVolatile(var1, var2)这是个native方法具体实现到JDK源码里去看了其实就是获取var1中var2偏移量处的值。var1就是AtomicIntegervar2就是我们前面提到的valueOffset,这样我们就从内存里获取到现在valueOffset处的值了compareAndSwapIntvar1, var2, var5, var5 var4换成compareAndSwapIntobj, offset, expect, update比较清楚意思就是如果obj内的value和expect相等就证明没有其他线程改变过这个变量那么就更新它为update如果这一步的CAS没有成功那就采用自旋的方式继续进行CAS操作private volatile int value;和unsafe.getAndAddInt(this, valueOffset, delta);
可以看出compareAndSwapIntobj, offset, expect, update中的obj为AtomicInteger类型
AtomicInteger的value值为volatile类型在看do {var5 this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 var4));这里是一个dowhile循环如果obj内的value和expect不相等
var5 this.getIntVolatile(var1, var2);一直会
执行即不断从内存中获取最新的值来与obj内的value进行比较直到相等为止。从这个字段可以看出复制代码CAS的缺点只能保证对一个变量的原子性操作长时间自旋会给CPU带来压力ABA问题