③. 数组类型原子类 (AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray)
- ①. 数组类型原子类,主要有三个AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
(了解即可)
- ②. 代码展示
public class AtomicIntegerArrayDemo { public static void main(String[] args) { //(1). 创建一个新的AtomicIntegerArray,其长度与从给定数组复制的所有元素相同。 int[]arr2={1,2,3,4,5}; AtomicIntegerArray array=new AtomicIntegerArray(arr2); //(2). 创建给定长度的新AtomicIntegerArray,所有元素最初为零。 //AtomicIntegerArray array=new AtomicIntegerArray(5); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); } System.out.println(); System.out.println("======="); array.getAndSet(0,1111); System.out.println("============"); System.out.println("将数字中位置为0位置上的元素改为:"+array.get(0)); System.out.println("数组位置为1位置上的旧值是:"+array.get(1)); System.out.println("将数组位置为1位置上的数字进行加1的处理"); array.getAndIncrement(1); System.out.println("数组位置为1位置上的新值是:"+array.get(1)); } }
④. 引用类型原子类 (AtomicReference、AtomicStampedReference、AtomicMarkableReference)
- ①. 引用类型原子类主要有三个: AtomicReference、AtomicStampedReference、AtomicMark ableReference
- ②. 使用AtomicReference来实现自旋锁案例
//自旋锁 public class AtomicReferenceThreadDemo { static AtomicReference<Thread>atomicReference=new AtomicReference<>(); static Thread thread; public static void lock(){ thread=Thread.currentThread(); System.out.println(Thread.currentThread().getName()+"\t"+"coming....."); while(!atomicReference.compareAndSet(null,thread)){ } } public static void unlock(){ System.out.println(Thread.currentThread().getName()+"\t"+"over....."); atomicReference.compareAndSet(thread,null); } public static void main(String[] args) { new Thread(()->{ AtomicReferenceThreadDemo.lock(); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {e.printStackTrace();} AtomicReferenceThreadDemo.unlock(); },"A").start(); new Thread(()->{ AtomicReferenceThreadDemo.lock(); AtomicReferenceThreadDemo.unlock(); },"B").start(); } }
- ③. AtomicStampedReference 解决ABA问题
- 携带版本号的引用类型原子类,可以解决ABA问题
- 解决修改过几次
- 状态戳原子引用
/** * Description: ABA问题的解决 * * @author TANGZHI * @date 2021-03-26 21:30 **/ public class ABADemo { private static AtomicReference<Integer> atomicReference=new AtomicReference<>(100); private static AtomicStampedReference<Integer> stampedReference=new AtomicStampedReference<>(100,1); public static void main(String[] args) { System.out.println("===以下是ABA问题的产生==="); new Thread(()->{ atomicReference.compareAndSet(100,101); atomicReference.compareAndSet(101,100); },"t1").start(); new Thread(()->{ //先暂停1秒 保证完成ABA try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get()); },"t2").start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("===以下是ABA问题的解决==="); new Thread(()->{ int stamp = stampedReference.getStamp(); System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference()); //暂停1秒钟t3线程 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName()+"\t 第2次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference()); stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName()+"\t 第3次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference()); },"t3").start(); new Thread(()->{ int stamp = stampedReference.getStamp(); System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference()); //保证线程3完成1次ABA try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } boolean result = stampedReference.compareAndSet(100, 2019, stamp, stamp + 1); System.out.println(Thread.currentThread().getName()+"\t 修改成功否"+result+"\t最新版本号"+stampedReference.getStamp()); System.out.println("最新的值\t"+stampedReference.getReference()); },"t4").start(); }
- ④. AtomicMarkableReference 不建议用它解决ABA问题
- 原子更新带有标志位的引用类型对象
- 解决是否修改(它的定义就是将状态戳简化位true|false),类似一次性筷子
- 状态戳(true/false)原子引用
- 不建议用它解决ABA问题
public class ABADemo{ static AtomicMarkableReference<Integer> markableReference = new AtomicMarkableReference<>(100,false); public static void main(String[] args){ System.out.println("============AtomicMarkableReference不关心引用变量更改过几次,只关心是否更改过======================"); new Thread(() -> { boolean marked = markableReference.isMarked(); System.out.println(Thread.currentThread().getName()+"\t 1次版本号"+marked); try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } markableReference.compareAndSet(100,101,marked,!marked); System.out.println(Thread.currentThread().getName()+"\t 2次版本号"+markableReference.isMarked()); markableReference.compareAndSet(101,100,markableReference.isMarked(),!markableReference.isMarked()); System.out.println(Thread.currentThread().getName()+"\t 3次版本号"+markableReference.isMarked()); },"线程A").start(); new Thread(() -> { boolean marked = markableReference.isMarked(); System.out.println(Thread.currentThread().getName()+"\t 1次版本号"+marked); //暂停几秒钟线程 try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } markableReference.compareAndSet(100,2020,marked,!marked); System.out.println(Thread.currentThread().getName()+"\t"+markableReference.getReference()+"\t"+markableReference.isMarked()); },"线程B").start(); } }
- ⑤. AtomicStampedReference和AtomicMarkableReference区别
- stamped – version number 版本号,修改一次+1
- Markable – true、false 是否修改过