线程原子操作

什么是原子操作?如何实现原子操作?
syn基于阻塞的锁的机制,1.被阻塞的锁的优先级很高。2.拿到所得线程一直不释放锁锁就GG.3.大量的竞争,消耗cpu,同时可能带来死锁或者其他的线程安全问题。

CAS的原理:

CAS(Compare And Swap),指令级别保证这是一个原子操作

三个运算符:一个内存地址V,一个期望值A,一个新值B.

基本思路:如果地址V上的值和期望的值A相等,就给地址V赋给新值B,如果不是,不做任何操作,循环(死循环、自旋)里不断进行CAS操作。

CAS的问题:

1.ABA问题,A–>B–>A,解决方法:版本号:A1–>B2–>A3(如果另一个线程修改V值假设原来是A,先修改成B,再修改回成A。当前线程的CAS操作无法分辨当前V值是否发生过变化,解决方法,添加版本号)

2.开销问题:循环不断执行CAS操作,如果CAS操作长期不成功,cpu不断循环,造成大量内存开销。

3.只能保证一个共享变量的原子操作。

代码示例:

public class CAS {
   static AtomicInteger atomicInteger = new AtomicInteger(0);
    public void increment(){
        for(;;){
            int i = atomicInteger.get();
            boolean suc = atomicInteger.compareAndSet(i,++i);
            if(suc)break;
        }
    }

    public static void main(String[] args) {
        new CAS().increment();
        System.out.println(atomicInteger.get());
    }
}

在这里插入图片描述
更新基本类型类

public class AtomicBaseTypeTest {

    static AtomicInteger atomicInteger = new AtomicInteger(12);
    static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
    static AtomicLong atomicLong = new AtomicLong(1000000000);
    public static void main(String[] args) {
        //Integer
        System.out.println(atomicInteger.addAndGet(12));//24
        System.out.println(atomicInteger.getAndAdd(12));//24
        System.out.println(atomicInteger.get());//36
        System.out.println(atomicInteger.compareAndSet(36,23));//true
        System.out.println(atomicInteger.get());//23
        //Boolean
        System.out.println(atomicBoolean.getAndSet(true));//false
        System.out.println(atomicBoolean.get());//true
        System.out.println(atomicBoolean.compareAndSet(true,false));//true
        System.out.println(atomicBoolean.compareAndSet(true,false));//false
        System.out.println(atomicBoolean.get());//false
        //long
        System.out.println(atomicLong.addAndGet(100));//1000000100
        System.out.println(atomicLong.getAndAdd(100));//1000000100
        System.out.println(atomicLong.getAndSet(123456789));//1000000200
        System.out.println(atomicLong.compareAndSet(123456789,987654321));//true
        System.out.println(atomicLong.get());//987654321
    }
}

更新数组类型类

public class AtomicArrayTest {
    static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);//数组长度为10,默认元素为0
    static AtomicLongArray atomicLongArray = new AtomicLongArray(10);
    static AtomicReferenceArray<Person> atomicReferenceArray = new AtomicReferenceArray<Person>(10);
    public static void main(String[] args) {
        //Integer
        System.out.println(atomicIntegerArray.addAndGet(0,3));//返回更新值0+3
        System.out.println(atomicIntegerArray.getAndAdd(0,4));//返回索引位置原值并更新,返回3
        System.out.println(atomicIntegerArray.decrementAndGet(0));//以原子方式将索引 i 的元素减 1,0+3+4-1=6
        System.out.println(atomicIntegerArray.getAndAccumulate(0,1,(int left, int right)->left+2*right));//返回前一个值6
        /*i - 索引、x - 更新值、accumulatorFunction - 作用函数*/
        System.out.println(atomicIntegerArray.get(0));//6+2*1=8
        System.out.println(atomicIntegerArray.decrementAndGet(0));//8-1=7
        System.out.println(atomicIntegerArray.updateAndGet(0,(int data)->data+1));//8+1
        //AtomicLongArray类似
        //Reference
        Person personA = new Person("zs",12);
        Person personB = new Person("ls",15);
        atomicReferenceArray.set(0,personA);
        System.out.println(atomicReferenceArray.get(0));
        System.out.println(atomicReferenceArray.compareAndSet(0,personA,personB));
        System.out.println(atomicReferenceArray.get(0));
    }

    private static class Person{
        private String name;
        private int age;
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

更新引用类型类

public class AtomicReferenceTest {
    static Person person = new Person("zs",15);
    static AtomicReference<Person> atomicReference = new AtomicReference<>(person);
    public static void main(String[] args) {
        System.out.println(atomicReference.compareAndSet(person,new Person("wemz",15)));//true
        System.out.println(atomicReference.getAndSet(new Person("ssd",20)));//Person{name='wemz', age=15}
        System.out.println(atomicReference.get().getName()+"++++"+atomicReference.get().getAge());//ssd++++20
    }

    private static class Person{
        private String name;
        private int age;
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

版本标记示例,AtomicStampedReference

public class AtomicStampedReferenceTest {
    static AtomicStampedReference atomicStampedReference = new AtomicStampedReference(0, 0);

    public static void main(String[] args) {
        System.out.println(atomicStampedReference.getStamp());//0
        System.out.println(atomicStampedReference.getReference());//0
        new Thread(() -> {
            atomicStampedReference.compareAndSet(atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println("当前atomicStampedReference为" + atomicStampedReference.getReference() + ";时间戳为" + atomicStampedReference.getStamp());
        }).start();
        new Thread(() -> {
            atomicStampedReference.compareAndSet(atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println("当前atomicStampedReference为" + atomicStampedReference.getReference() + ";时间戳为" + atomicStampedReference.getStamp());
        }).start();
    }
}

0
0
当前atomicStampedReference为1;时间戳为1
当前atomicStampedReference为2;时间戳为2

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值