Java并发 - 预备知识

本文部分摘自书籍《Java并发编程的艺术》

此系列文章对应GitHub地址

预备知识

悲观锁

当有线程占有锁时,其它需要锁的线程会被挂起,等待持有锁的线程释放锁,具有强烈的独占性和排他性。悲观锁假设最悲观的情况(也就是会发生并发冲突),为了避免并发冲突,会使得其它需要锁的线程挂起,以免可能发生的数据完整性破坏情况,而挂起和恢复会造成很大的开销,挂起期间,线程不能做任何事情,所以悲观锁的缺点显而易见。例子:synchronized(独占锁的应用)。

乐观锁

假设并发线程在处理时不会彼此互相影响,各个线程能够在不产生锁的情况下处理各自影响的数据。若出现冲突而失败,会进行重试,直到成功为止。可以看出,若数据竞争的概率小的情况下,使用乐观锁更好。例子:CAS

CPU内存屏障(memory barrier)

程序运行时内存实际的访问顺序和程序代码编写的顺序往往不一定一致,这被称为内存乱序访问。内存乱序访问出现的理由是为了提升程序运行的性能。主要发生在两个阶段:编译时,编译器优化造成的指令重排;运行时,CPU间交互引起的内存乱序访问。而内存屏障恰恰是一个能使得内存访问有序的一组指令。内存乱序一般不会有问题,但是部分程序逻辑对内存访问顺序依赖很高,可能会造成程序逻辑错误,特别是涉及到多线程的程序。

CPU缓存行(cache line)

CPU内的缓存(一级缓存、二级缓存等)可以分配的最小存储单位,由于不同的CPU的缓存行大小不同,假设缓存行为32字节,那么一个缓存行可以存储32字节的数据,而缓存从内存读入数据也会将目标数据所在分组的32字节数据一起读取到该缓存行,也就是说可能会读入一些我们不需要的数据到缓存行。

CPU原子操作(atomic operations)

不可中断的一个或一系列操作。

CPU缓存行填充(cache line fill)

简单来说就是读入内存数据到缓存行。前面CPU缓存行已经说到了。重点就是,会读取目标数据所在分组的缓存行大小(前面说的是32字节)的数据。

CPU缓存行命中(cache hit)

进行缓存行填充的内存位置任然是下次处理器访问的地址时,处理器从缓存行中读取操作数,而不是从内存中读取。

CPU写命中(write hit)

当处理器将操作数写回到一个内存缓存的区域时,他首先会检查这个缓存的内存地址是否在缓存中,如果存在一个有效的缓存行,则处理器将这个操作数写回到川村,而不是写回到内存,这个操作被称为写命中。

CPU写缺失(write misses the cache)

一个有效的缓存行被写入到不存在的内存区域。

比较并交换 (Compare and Swap即CAS)

CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不进行交换。

CPU流水线(CPU pipeline)

CPU流水线的工作方式就像工业生产上的装配流水线,在CPU中由5-6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5-6步后再由这些电路单元分别执行,这样就能实现在一个CPU始终周期完成一条指令,因此提高CPU的运算书读。

CPU内存顺序冲突(Memory order violation)

内存顺序冲突一般是由假共享引起的,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值