Java并发编程

并发编程

并发:在一段时间内,多个事情交替执行
并行:多件事情在同一时刻同时发生

在例如买票,抢购等场景下,有大量的请求访问同一个资源.会出现线程安全的问题,需要通过编程来控制解决多个线程依次访问资源,称为并发编程.

并发编程的根本原因

Java 内存模型(Java Memory Model,JMM)

是Java虚拟机的一种工作模式.将内存分为主内存和工作内存.变量数据存储在主内存中,线程操作变量时,会讲述内存中的数据复制一份到工作内存中.在工作内存中完成操作后了,再写回到主内存中.

多线程核心根本问题

不可见性

多个线程分别同时对共享数据进行操作,彼此之间不可见,操作完写回主内存时可能出现问题

无序性

为了优化性能对一些代码指令的执行重新排序

非原子性

原子性是一个或多个操作在CPU执行的过程中不被中断的特性.线程切换导致原子性出现问题.
例如: i++ 至少要三条CPU指令
1.先从主内存加载到工作内存
2.操作数据
3.再从工作内存写回到主内存

解决多线程问题办法

让不可见变为可见
让无序变为有序
非原子执行变为原子

volatile关键字

volatile修饰的变量被一个线程修改后,能在其他线程中立即可见.
volatile修饰的变量,在执行时不会被重新排序
volatile不能解决原子性问题

底层实现原理

在底层使用指令级别进行控制.有序性实现:volatile修饰的变量在操作前,添加内部屏障,不让指令干扰.可见性实现:通过Lock前缀指令+MESI缓存一致性协议来实现.发送一个Lock给CPU,CPU在执行完操作后会立即将值刷新到内存,MESI将数据写回到主内存,其他工作内存嗅探后,将自己工作内存数据过期,重新从主内存中读取最新的数据.

加锁实现原子性

通过加锁的方式,让线程互斥来保证一次只有一个线程对共享资源访问.

synchronized : 关键字,修饰代码块,方法.自动获取锁,自动释放锁
ReentrantLock : 类,只能对某段代码修饰.需要手动加锁,手动释放锁.

原子类实现

在java中还提供一些原子类,在低并发情况下使用,是一种无锁实现原子性.采用CAS机制(Compare-And-Swap  比较并变换)

原理

采用自旋思想.第一次获取内存值到工作内存中, 存储起来作为预期值, 然后对数据进行修改,再将工作内存中值写入到主内存.在写入之前要进行判断,用预期值与主内存中的值进行比较, 如果预期值与主内存中值一致, 说明没有其他线程修改, 将更新数的值,写入到主内存. 如果预期值与主内存中值不一致, 说明其他线程修改了主内存的值, 这时就需要重复操作整个过程.

优点: 不加锁,所有的线程都可以对共享数据操作;适合低并发时使用;由于不加锁,其他线程不需要阻塞,效率高.

缺点:大并发时,不停自旋判断,导致cpu占用率高;会出现ABA问题(通过设置版本号,每次操作改变版本号).
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值