多线程和高并发(三) Compare And Swap

多线程和高并发(三)| Compare And Swap

系列文章目录

多线程和高并发(一) Thread
多线程和高并发(二) volatile关键字
多线程和高并发(三) Compare And Swap
多线程和高并发(四) 线程间通信
多线程和高并发(五) ThreadLocal & Lock
多线程和高并发(六) ReentrantLock
多线程和高并发(七) 线程池



线程同步

CAS(Compare And Swap)

是由硬件实现的,CAS可以将读改写(read - modify - write)这类的操作转化为原子操作。

i++ 自增操作包括三个操作:

  • 从内存中读取i的值
  • 对i的值加1
  • 把加1 的值之后的值保存到主内存

CAS原理:在数据更新到主内存时,在读取主内存的值,如果期望值和主内存值相同,则将修改值更新到主内存中

/**
 * @author 奋斗的蜗牛_Z99
 * @CopyRight (C) https://blog.csdn.net/mr_zhu_wenxing?spm=1001.2101.3001.5343
 * @date 2021/5/6
 * @description CAS模拟
 */
public class CAS extends Thread {
    //volatile确保读取值从主内存读取(可见性)
    private volatile static int value = 0;

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            getAndIncrement();
        }
        System.out.println(value);
    }

    //此方法需要保障同步
    static synchronized boolean compareAndSwap(int expectValue, int newValue) {
        if (value == expectValue) {
            value = newValue;
            return true;
        } else
            return false;
    }

    int getAndIncrement() {
        int oldValue;
        int newValue;
        do {
            oldValue = value;
            newValue = oldValue + 1;
        } while (!compareAndSwap(oldValue, newValue));
        return newValue;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            new CAS().start();
        }
    }
}

这种操作只满足非ABA修改,比如共享变量 count = 0

  • A 线程对 count 值修改为 10
  • B 线程对 count 值修改为 20
  • C 线程对 count 值修改为 0

这就是CAS的A->B->A更新,如果需要规避ABA问题,可以为共享变量引入一个修订号(时间戳),每次更改修订号加一,ABA变量更新过程变量: [A,0] ->[B,1]->[A,2],AtomicStampedReference类就是基于这种思想。

原子变量类

原子变量类是基于CAS实现的,对共享变量进行read-modify-write 更新操作时,通过原子变量类可以保障操作的原子性和可见性,原子类有12个:

分组原子变量类
基本数据型AtomicInteger
AtomicLong
AtomicBoolean
数组型AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
字段更新器AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
引用型AtomicReference
AtomicStampedReference
AtomicMarkableReference

详细使用略

线程间的通信

等待/通知机制

什么是等待通知机制

在单线程编程中,要执行的操作需要满足一定的条件才能执行,可以把这个操作放在 if语句块中在多线程编程中,可能 A 线程的条件没有满足只是暂时的, 稍后其他的线程 B 可能会更新条件使得 A 线程的条件得到满足。可以将A线程暂停,直到它的条件得到满足后再将 A 线程唤醒它的伪代码:

atomics{ 
    //原子操作 
    while( 条件不成立 ){
        等待 
    }
    当前线程被唤醒条件满足后,继续执行下面的操作 
}
等待通知机制的实现

等待

  • Object的wait()方法可以暂停执行,直到接到通知或中断为止
  • 只能被锁对象调用
  • 调用后会释放锁对象,进入WAITING状态
//在调用 wait()方法前获得对象的内部锁
synchronized( 锁对象 ){
    while( 条件不成立 ){
        //通过锁对象调用 wait()方法暂停线程,会释放锁对象
        锁对象.wait(); 
    }
    //线程的条件满足了继续向下执行 
}

通知唤醒

  • Object 类的notify()可以唤醒线程,只能被锁对象调用
  • notify()随机唤醒一个线程
  • 没有锁对象调用notify/waitd方法会抛出IllegalMonitorStateException
  • 调用 notify()方法后,并不会立即释放锁对象,需要等当前同步代码块执行完后才会释放锁对象
synchronized( 锁对象 ){
    //执行修改保护条件的代码 
    //唤醒其他线程 
    锁对象.notify(); 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值