摘要:当前可用的原子数组有和,分别表示整数数组型数组和普通的对象数组。摘自实战高并发程序设计一书实战高并发程序设计中的指针类实战高并发程序设计无锁的对象引用实战高并发程序设计带有时间戳的对象引用
除了提供基本数据类型外,JDK还为我们准备了数组等复合结构。当前可用的原子数组有:AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray,分别表示整数数组、long型数组和普通的对象数组。
这里以AtomicIntegerArray为例,展示原子数组的使用方式。
AtomicIntegerArray本质上是对int[]类型的封装。使用Unsafe类通过CAS的方式控制int[]在多线程下的安全性。它提供了以下几个核心API:
//获得数组第i个下标的元素 public final int get(int i) //获得数组的长度 public final int length() //将数组第i个下标设置为newValue,并返回旧的值 public final int getAndSet(int i, int newValue) //进行CAS操作,如果第i个下标的元素等于expect,则设置为update,设置成功返回true public final boolean compareAndSet(int i, int expect, int update) //将第i个下标的元素加1 public final int getAndIncrement(int i) //将第i个下标的元素减1 public final int getAndDecrement(int i) //将第i个下标的元素增加delta(delta可以是负数) public final int getAndAdd(int i, int delta)
下面给出一个简单的示例,展示AtomicIntegerArray使用:
01 public class AtomicIntegerArrayDemo { 02 static AtomicIntegerArray arr = new AtomicIntegerArray(10); 03 public static class AddThread implements Runnable{ 04 public void run(){ 05 for(int k=0;k<10000;k++) 06 arr.getAndIncrement(k%arr.length()); 07 } 08 } 09 public static void main(String[] args) throws InterruptedException { 10 Thread[] ts=new Thread[10]; 11 for(int k=0;k<10;k++){ 12 ts[k]=new Thread(new AddThread()); 13 } 14 for(int k=0;k<10;k++){ts[k].start();} 15 for(int k=0;k<10;k++){ts[k].join();} 16 System.out.println(arr); 17 } 18 }
上述代码第2行,申明了一个内含10个元素的数组。第3行定义的线程对数组内10个元素进行累加操作,每个元素各加1000次。第11行,开启10个这样的线程。因此,可以预测,如果线程安全,数组内10个元素的值必然都是10000。反之,如果线程不安全,则部分或者全部数值会小于10000。
程序的输出结果如下:
[10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000]
这说明AtomicIntegerArray确实合理地保证了数组的线程安全性。
摘自《实战Java高并发程序设计》一书
【实战Java高并发程序设计1】Java中的指针:Unsafe类
【实战Java高并发程序设计2】无锁的对象引用:AtomicReference
【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65569.html
摘要:在本例中,讲述的无锁来自于并发包我们将这个无锁的称为。在这里,我们使用二维数组来表示的内部存储,如下变量存放所有的内部元素。为什么使用二维数组去实现一个一维的呢这是为了将来进行动态扩展时可以更加方便。 我们已经比较完整得介绍了有关无锁的概念和使用方法。相对于有锁的方法,使用无锁的方式编程更加考验一个程序员的耐心和智力。但是,无锁带来的好处也是显而易见的,第一,在高并发的情况下,它比有锁...
摘要:有时候,由于初期考虑不周,或者后期的需求变化,一些普通变量可能也会有线程安全的需求。它可以让你在不改动或者极少改动原有代码的基础上,让普通的变量也享受操作带来的线程安全性,这样你可以修改极少的代码,来获得线程安全的保证。 有时候,由于初期考虑不周,或者后期的需求变化,一些普通变量可能也会有线程安全的需求。如果改动不大,我们可以简单地修改程序中每一个使用或者读取这个变量的地方。但显然,这...
摘要:并发包将这种无锁方案封装提炼之后,实现了一系列的原子类。无锁方案相对互斥锁方案,最大的好处就是性能。作为一条指令,指令本身是能够保证原子性的。 前面我们多次提到一个累加器的例子,示例代码如下。在这个例子中,add10K() 这个方法不是线程安全的,问题就出在变量 count 的可见性和 count+=1 的原子性上。可见性问题可以用 volatile 来解决,而原子性问题我们前面一直都...
摘要:实战高并发程序设计连载中的指针类和非常类似,不同之处就在于是对整数的封装,而则对应普通的对象引用。这样,当前线程就无法正确判断这个对象究竟是否被修改过。摘自实战高并发程序设计一书 【实战Java高并发程序设计】连载1–Java中的指针:Unsafe类 AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,而Atomi...
摘要:介绍中无锁的线程安全整数,一个提供原子操作的的类。在语言中,和操作并不是线程安全的,在使用的时候,不可避免的会用到关键字。而则通过一种线程安全的加减操作接口。就是的意思,比较并操作。有个操作数,内存值,旧的预期值,要修改的新值。 【介绍 JAVA 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的...
阅读 2533·2021-10-09 09:44
阅读 640·2019-08-30 15:44
阅读 2994·2019-08-29 18:46
阅读 1133·2019-08-29 18:38
阅读 557·2019-08-26 10:44
阅读 2431·2019-08-23 16:07
阅读 1089·2019-08-23 15:38
阅读 4085·2019-08-23 14:02