zoukankan      html  css  js  c++  java
  • Java并发编程原理与实战十三:JDK提供的原子类原理与使用

    原子更新基本类型

    原子更新数组

    原子更新抽象类型

    原子更新字段

    原子更新基本类型:

     
    package com.roocon.thread.t8;

    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicIntegerArray;

    public class Sequence {
    private AtomicInteger value = new AtomicInteger(0);
    private int [] s = {2,1,4,6};
    AtomicIntegerArray a = new AtomicIntegerArray(s);

    public int getNext(){
    a.getAndIncrement(2);//给下标为2的元素加1
    a.getAndAdd(2, 10);//获取下标为2的元素,并且加10
    for (int i=0; i < a.length(); i++){
    System.out.println(a.get(i));
    }
    return value.getAndIncrement();
    }

    public static void main(String[] args) {
    Sequence sequence = new Sequence();
    new Thread(new Runnable() {
    @Override
    public void run() {
    while (true){
    System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }).start();
    new Thread(new Runnable() {
    @Override
    public void run() {
    while (true){
    System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }).start();
    new Thread(new Runnable() {
    @Override
    public void run() {
    while (true){
    System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }).start();
    }
    }
     

    运行结果:

     
    Thread-0 0
    Thread-1 1
    Thread-2 2
    Thread-0 3
    Thread-1 4
    Thread-2 5
    ...
     
     
    package com.roocon.thread.t8;
    
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicIntegerArray;
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    import java.util.concurrent.atomic.AtomicReference;
    
    public class Sequence {
        private AtomicInteger value = new AtomicInteger(0);
        AtomicReference<User> user = new AtomicReference<>(); //对user的set和get执行原子操作
        AtomicIntegerFieldUpdater<User> old =  AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
    
        public int getNext(){
            User user = new User();
            System.out.println(old.getAndIncrement(user));
            System.out.println(old.getAndIncrement(user));
            System.out.println(old.getAndIncrement(user));
            return value.getAndIncrement();
        }
    
        public static void main(String[] args) {
            Sequence sequence = new Sequence();
            new Thread(new Runnable() {
                @Override
                public void run() {
                       System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
                       try {
                           Thread.sleep(100);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                   }
            }).start();
        }
    }
     

    运行结果:

    0
    1
    2
    Thread-0 0

    对CAS的源码理解:--初步理解

    在AtomicInteger中有这样一段源码:

     
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }

    public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
     
     

    其中,compareAndSwap就是CAS的缩写。如果prev和next不相等,则返回true。否则,返回false。最终是通过unsafe来实现的。

    以上代码表示,如果compareAndSet返回true,则while条件为false,退出循环,返回prev值。如果compareAndSet返回false,则while为true,继续执行循环体,重新获取prev的值,重新获取更新值,直到返回的compareAndSet值为true。

    演示源码大致步骤如下:

    
     Object prev = get(); //1
            next = prev + 1;
            boolean flag = cas(prev, next);
            if (flag) {
                return prev;
            }else {
                go to 1
            } Object pre

    参考资料:

    《java并发编程与实战》龙果学院

  • 相关阅读:
    mysql查询不同用户(操作记录)的最新一条记录
    Mysql复制一条或多条记录并插入表|mysql从某表复制一条记录到另一张表
    获取股票数据接口(腾讯)
    uni-app微信相关开发问题记录:微信分享报错"包名不对,请检查包名是否与开放平台填写一致"、Android微信支付只能调起一次的问题、App微信登录与公众号微信登录的unionid不一致
    如何生成Android签名证书、安卓签名获取工具获取APP签名报错:NameNotFoundException: Signs is null的问题
    uniapp微信APP支付踩坑指南:报错errMsg: "requestPayment:fail errors"
    浅析判断一个APP是原生的还是H5页面
    uniapp nvue开发注意事项
    浅析Redis(整合Springboot、订阅发布、集群、雪崩、穿透、击穿)
    uniapp引入iconfont图标及解决真机中iconfont不显示的问题
  • 原文地址:https://www.cnblogs.com/pony1223/p/9404990.html
Copyright © 2011-2022 走看看