并发编程初解

1.概述

        java是最先支持多线程开发的语言之一,多线程技术使得程序的响应更快,可以再进行其他工作的同时一直处于活动状态。

        性能提升的本质就是榨取硬件的剩余价值即就是提高硬件的利用率。

        并发编程所带来的问题:

        安全性问题(访问共享变量)

        性能问题(线程切换所导致的CPU开销)

2.并行与并发

        并行:同一时间节点,多个任务同时进行

        并发:同一时间结点,多个任务依次交替执行。

        对于并发而言,操作系统存在一个任务调度片,线程切换即就是时间片太过短暂,线程切换的速度非常快,因此在微观上看并发是串行的,宏观上来看就是并行的。

        举个例子来说:

        并行:两个人在两台饮水机在同时执行接水操作

        并发:两个人在一台饮水机依次交替接水

3.并发编程的核心问题

核心问题即就是缓存所带来的可见性问题,编译优化所带来的有序性问题以及线程切换所带的原子性问题。

3.1可见性

一个线程对共享变量的修改,另外一个线程立马可以看到,称之为可见性。

在多线程的时代,每个CPU都有自己本地缓存,缓存又只对处理器的内核可见,导致了缓存的内容与内存的内容可能会不一致。处理器采用写缓冲区来保存写入内存的数据,而写缓冲区采用批处理的方式刷新内存,也就是说缓存中的数据并不会立即刷新到内存中,这也就导致了可见性问题。

3.2有序性

程序按照代码的先后顺序之星称之为有序性。

在程序执行的过程中,编译期经常会为了优化程序性能,从而乱序执行,也就导致了有序性问题。CPU的读等待同时指令执行是CPU执行乱序的根源。............................0

3.3原子性

一个线程或多个线程在执行的过程中不被中断的特性称之为原子性。

线程切换导致了原子性问题,具有原子性的量,同一时刻只能有一个线程执行操作。

4.volatile关键字

        volatile修饰一个共享变量时,可以保证可见性与有序性,无法保证其原子性

底层实现原理:

        使用内存屏障,内存屏障可以限制处理器以及编译器做出的指令重排

        volatile所修饰的共享变量编译为汇编语言之后会多出一个lock前缀,通过lock指令前缀+MESI缓存一致性协议可以保证操作的可见性。

        有序性实现:主要通过对valitale修饰的变量在进行读写操作前后加入内存屏障来限制指令的重排。

        可见性实现:主要通过lock前缀指令+MESI缓存一致性协议实现;对volitale修饰的量进行写操作时,JVM会给CPU发送一个lock指令前缀,CPU在执行完写操作时,会立即将数据刷新到内存中,因为MESI缓存一致性协议,其它线程会对主线进行嗅探即就是与内存值作对比,查看自己的本地缓存是否被修改过,一旦被修改就会过期掉本地缓存,从主线中刷新到最新的内存值,这样就保证了可见性。

5。如何保证原子性?

5.1synchronized关键字

        synchronized是一种通用的技术方案,JAVA语言提供的synchronized关键字,就是锁的一种实现,synchronized是一种独占锁、排它锁;并不能改变CPU时间片的切换,但是synchronized锁可以产生阻塞,当一个线程对共享变量进行修改时,其它的线程必须在外面排队等候,因次同一时刻只能有一个线程进行操作。因此synchronized一定可以保证原子性。

5.2原子变量类

        javaJUC包中存在两个包,一个是locks包,另一个是atomic包;两者都可以解决原子性问题。

       synchronized是一种阻塞式实现原子性

        原子变量则是非阻塞式实现原子性

        原子变量类的原理:通过volatile关键字+CAS算法实现原子性

5.3CAS算法

        CAS(compare and swap)比较并交换,CAS算法是硬件对并发操作的一种支持,是乐观锁的一种实现方式,采用自旋锁的思想,是一种轻量级锁

        CAS算法的实现原理:每次判断内存值是否与预估值相同,如果不相同,则证明内存值已经被其他线程修改过了。则需要拿到最新值作为新的预估值,然后再次与内存值作比较;该线程就会不断的判断内存值是否被修改过,这就是自旋的思想。

        CAS算法共有三个操作数

        预估值:A 

        内存值:V

        更新值:B

当且仅当预估值与内存值相同时,将内存值赋给更新值

        CAS算法的优点:当判断不成功时,不会更新值,也不会产生阻塞,继续判断执行,提高了效率。

        CAS算法的缺点:不断地自旋,会导致CPU的消耗,高并发的情况下可能会导致CPU跑满。

        CAS算法所带来的问题:ABA问题:即就是当一个线程将内存值由A修改为B,另外一个线程将B又修改为了A;预估值与内存值相比较还是相同;CAS算法就无法判断内存值是否被修改过。

        解决方案:使用类版本添加号,每次对内存的修改都添加上类版本添加号,判断时先判断内存值是否相同,再判断类版本添加号是否相同,这样就可以避免ABA问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值