CAS

CAS

CAS(Compare and Swap,比较并交换)基本思想是,在更新某个值之前,先比较其内存中的值是否与预期的值相等,如果相等,则进行更新;如果不相等,则不更新。

结合 CAS 和 volatile 可以实现无锁并发,适用于线程数少、多核 CPU 的场景下。

  • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再 重试呗。
  • synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想 改,我改完了解开锁,你们才有机会。
  • CAS 体现的是无锁并发、无阻塞并发,请仔细体会这两句话的意思 因为没有使用 synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一 但如果竞争激烈,可以想到重试必然频繁发生,反而效率会受影响

原子整数

AtomicInteger i = new AtomicInteger(0);

 // 获取并自增(i = 0, 结果 i = 1, 返回 0),类似于 i++
 System.out.println(i.getAndIncrement());

 // 自增并获取(i = 1, 结果 i = 2, 返回 2),类似于 ++i
 System.out.println(i.incrementAndGet());

 // 自减并获取(i = 2, 结果 i = 1, 返回 1),类似于 --i
 System.out.println(i.decrementAndGet());

 // 获取并自减(i = 1, 结果 i = 0, 返回 1),类似于 i-
System.out.println(i.getAndDecrement());

 // 获取并加值(i = 0, 结果 i = 5, 返回 0)
System.out.println(i.getAndAdd(5));

 // 加值并获取(i = 5, 结果 i = 0, 返回 0)
System.out.println(i.addAndGet(-5));

 // 获取并更新(i = 0, p 为 i 的当前值, 结果 i = -2, 返回 0)
// 其中函数中的操作能保证原子,但函数需要无副作用
System.out.println(i.getAndUpdate(p -> p - 2));

 // 更新并获取(i = -2, p 为 i 的当前值, 结果 i = 0, 返回 0)
// 其中函数中的操作能保证原子,但函数需要无副作用
System.out.println(i.updateAndGet(p -> p + 2));

 // 获取并计算(i = 0, p 为 i 的当前值, x 为参数1, 结果 i = 10, 返回 0)
// 其中函数中的操作能保证原子,但函数需要无副作用
// getAndUpdate 如果在 lambda 中引用了外部的局部变量,要保证该局部变量是 final 的
// getAndAccumulate 可以通过 参数1 来引用外部的局部变量,但因为其不在 lambda 中因此不必是 final
 System.out.println(i.getAndAccumulate(10, (p, x) -> p + x));

 // 计算并获取(i = 10, p 为 i 的当前值, x 为参数1, 结果 i = 0, 返回 0)
// 其中函数中的操作能保证原子,但函数需要无副作用
System.out.println(i.accumulateAndGet(-10, (p, x) -> p + x))

原子引用

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

public class Test07 {
    public static void main(String[] args) throws InterruptedException {
        AtomicReference<BigDecimal> bigDecimal = new AtomicReference<>(new BigDecimal(10000));
        List<Thread> threads = new ArrayList<>();
        long start = System.nanoTime();
        for(int i=0;i<10000;i++){
            Thread thread = new Thread(() -> {
                while (true){
                    BigDecimal pre = bigDecimal.get();
                    if (bigDecimal.compareAndSet(pre,pre.subtract(new BigDecimal(1)))) {
                        break;
                    }
                }
            });
            threads.add(thread);
        }
        for(Thread t:threads){
            t.start();
        }
        for (Thread t:threads){
            t.join();
        }
        long end = System.nanoTime();
        System.out.println(bigDecimal.get() + " cost: " + (end - start) / 1000_000 + " ms");
    }
}

Unsafe

public class GetUnsafe {
	public static void main(String[] args) throws Exception {
		// 通过反射获得Unsafe对象
		Class unsafeClass = Unsafe.class;
		// 获得构造函数,Unsafe的构造函数为私有的
		Constructor constructor = unsafeClass.getDeclaredConstructor();
		// 设置为允许访问私有内容
		constructor.setAccessible(true);
		// 创建Unsafe对象
		Unsafe unsafe = (Unsafe) constructor.newInstance();
		
		// 创建Person对象
		Person person = new Person();
		// 获得其属性 name 的偏移量
		Field field = Person.class.getDeclaredField("name");
		long offset = unsafe.objectFieldOffset(field);

		// 通过unsafe的CAS操作改变值
		unsafe.compareAndSwapObject(person, offset, null, "Nyima");
		System.out.println(person);
	}
}

class Person {
    // 配合CAS操作,必须用volatile修饰
 	volatile String name;


	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				'}';
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林小果呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值