多线程_volatile+CAS

volatile作用:

  1. 内存可见性
    a. MESI
    b. 保证cpu之间缓存一致性
    c. volatile 只能可见基本类型,如果是个引用类型,只能可见的是地址值

  2. 禁止指令重排序

jvm中Object o = new Object() 对象的创建过程

  1. 在jvm的堆中申请内存(提供默认初始值)
  2. 给对象赋予成员变量的值
  3. 把内存地址值给了方法栈中的o

volication的特性
• 数据可见性
• MESI
• 缓存一致性协议
• 阻止cpu命令重排序
• loadfence 源语命令
• storefence 源语命令
• 可以阻止两种命令不能交叉

该代码旨在证明volatile的可见性
• 一个线程的栈内存中有全局变量缓存
• 如果不加volatile,不会及时读取全局变量的值
• 有坑:while循环中 system.out 会刷新内存

private static Boolean isRunning = true;
    private static void run() {
        while (isRunning) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
            System.out.println("程序开始跑啊跑啊跑.....");
        }
        System.out.println("程序结束了");
    }
    public static void main(String[] args) {
        new Thread(() -> {
            run();
        }).start();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
            System.out.println("改变成员变量为false");
            isRunning = false;
        }).start();
    }

单例模式
饿汉式

public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton();
    private HungrySingleton() {
    }
    public static HungrySingleton getInstance() {
        return instance;
    }
    public static void main(String[] args) {
        LazySingleton instance1 = LazySingleton.getInstance();
        LazySingleton instance2 = LazySingleton.getInstance();
        if(instance1 == instance2){
            System.out.println("两个地址值一样");
        }
    }
}

懒汉式(线程安全的)

public class LazySingleton {
    private static volatile LazySingleton instance = null;    //保证 instance 在所有线程中同步
    private LazySingleton() {
    }    //private 避免类在外部被实例化
    public static LazySingleton getInstance() {
        //getInstance 方法前加同步
        if (instance == null) {
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
    public static void main(String[] args) {
    }
}

volatile只能保证线程的可见性,但是做不到保证数据一致性所以需要跟synchronized配合

public class Thread_07_volatile_synchronazed {
    volatile int count = 0;
    synchronized void insertCount(){
        try{
            Thread.sleep(1);
        }catch (Exception e){
        }
        for (int i = 0; i < 1000; i++) {
            count++;
        }
    }
    public static void main(String[] args) {
        Thread_07_volatile_synchronazed t = new Thread_07_volatile_synchronazed();
        List<Thread> threadList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            threadList.add(new Thread(t::insertCount,"__name"+i));
        }
        threadList.forEach((o)->o.start());
        //挺巧妙的写法,可以等同于 CountDownLatch  但是如果线程报错了,得杀死线程(不建议)
        threadList.forEach((o)->{
            try{
                o.join();
            }catch (Exception e){
            }
            System.out.println(o.getName()+"结束了");
        });
        System.out.println(t.count);
    }
}

AtomicInteger 线程安全的类

public class Thread_08_volatile_atomicInteger {
    AtomicInteger count = new AtomicInteger(0);
    void insertCount(){
        try{
            Thread.sleep(1);
        }catch (Exception e){
        }
        for (int i = 0; i < 1000; i++) {
            count.incrementAndGet();
        }
    }
    public static void main(String[] args) {
        Thread_08_volatile_atomicInteger t = new Thread_08_volatile_atomicInteger();
        List<Thread> threadList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            threadList.add(new Thread(t::insertCount,"__name"+i));
        }
        threadList.forEach((o)->o.start());
        //挺巧妙的写法,可以等同于 CountDownLatch  但是如果线程报错了,得杀死线程(不建议)
        threadList.forEach((o)->{
            try{
                o.join();
            }catch (Exception e){
            }
        });
        System.out.println(t.count);
    }
}

CAS(无锁 乐观锁)
• Compare And Set
• cas(插入值 o,期望值 expected,新值 newValue)
• if o == e
• o = newValue
• else
• try angin or fail
• CAS是CPU级别的指令,不存在多线程情况
在这里插入图片描述

ABA问题
• 刚开始是A 处理了一下是B 后来又变回A
• CAS解决不了ABA问题,因为你的插入值没有变
• 如果是基本类型,不影响,如果是引用类型,会有影响
• 解决方案,加版本
• A 版本 1.0
• A ==> B 版本 2.0
• B ==> A 版本 3.0
• CAS的时候加上版本一起比较

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值