并发

记录并发相关知识点

内存模型

Java线程-工作内存-内存操作-主内存

每个Java线程都有自己对应的工作内存,工作内存线程私有,必须通过主内存进行数据交换。

内存间交互操作

主内存和工作内存之间有具体的交互协议,实现从主内存到交互内存的拷贝和同步。有lock,unlock,read,load,use,assign,store,write。规定了一系列的访问规则。

volatile关键字

  • 可见性:一个线程对volatile修饰的变量修改之后,立刻对其它线程可见。但是,有些运算可能并非原子的,不能保证并发安全。使用情况需要满足:
    • 运算结果并不依赖变量的当前值,或者能够确保只有单一线程能够修改变量的值。
    • 变量不需要与其它的状态共同参与不变性约束。
  • 禁止语义重排
    • 相当于添加了内存屏障

内存模型特性

  • 对于long和double类型需要注意JVM对64数据是否为原子的
  • 原子性:synchronized关键字
  • 可见性:volatile synchronized final关键字实现
  • 有序性:volatile

happen-before原则

Java内存模型下有一些天然的先行发生关系:

  • 程序次序规则
  • 管程锁定规则
  • volatile规则
  • 线程启动规则
  • 线程终止规则
  • 线程中断规则
  • 对象终结规则
  • 传递性

Java线程实现

  • 线程实现
    • 内核级线程
      • 一般通过轻量级进程包装内核线程,然后再使用
      • 轻量级进程和线程之间1:1
      • 由于需要在用户态和内核态之间切换,系统调用代价较高
    • 用户线程
      • 线程建立,同步,销毁,调度完全在用户态中完成。
      • 进程和线程之比为1:N
    • 用户线程加轻量级线程
      • 混合使用,进程和线程之间N:M
  • Java线程实现
    • 1.2之前是用户线程
    • 1.2之后是基于操作系统原生线程来实现的
  • Java线程调度
    • 协同式线程调度:线程执行完通知其它线程执行
      • 好处是实现简单
      • 坏处是线程执行时间不可控制,如果一个线程编写有问题,容易造成阻塞。
    • 抢占式线程调度
      • 每个线程由系统来分配执行时间。
  • 线程状态转换
    • 新建
    • 运行:包括系统线程中的Running和Ready,有可能在等待CPU调度
    • 无限期等待:需要等待被其它线程唤醒。
      • 没有设置TimeOut的Object.wait()
      • 没有设置TimeOut的Thread.join()
      • LockSupport.park()
    • 有限期等待:一定时间之后被系统自动唤醒
      • Thread.sleep()
      • 设置TimeOut的Object.wait()
      • 设置TimeOut的Thread.join()
      • LockSupport.parkNanos()
      • LockSupport.parkUntil()
    • 阻塞:等待获得排它锁,在等待另一个线程释放锁时发生。
    • 结束

线程安全

  • 定义
    • 当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步,或者在调用代码代码不必作其他的协调,这个类的行为仍然是正确的,那么称这个类是线程安全的。
  • 特征
    • 代码本身封装了所有必要的正确性保障手段
  • Java操作共享数据分类(线程安全程度由强到弱)
    • 不可变
      • String,Long,Double,BigInteger等为不可变对象
      • AtomicInteger和AtomiLong则为可变类
    • 绝对线程安全
      • java.util.Vector,方法被synchronized修
    • 相对线程安全:特定的执行顺序需要同步
      • Vector,HashTable,Collections
    • 线程兼容:对象本身是线程非线程安全的,但是可以使用同步手段让对象在并发情况下安全使用。
    • 线程对立:无法同步的代码。
  • 线程安全的实现
    • 互斥同步
      • 可以使用临界区,互斥量,和信号量、
      • synchronized关键字,Java里面会在同步块前后加上monitorenter和monitorexist关键字,重量级操作
      • ReentrantLock和synchronized很相似,写法上不太同
        • 等待可中断
        • 可实现公平锁
        • 锁绑定多个条件
    • 非阻塞同步
      • 基于冲突检测和乐观并发策略,先操作,有冲突,再补偿,需要硬件指令支持。
      • Test-and-set,Fetch-and-Increment,Swap,Compare-and-Swap(CAS),Load-Linked/Store-Conditional
    • 无同步方案
      • 可重入代码
      • 线程本地存储
  • 锁优化(1.5到1.6)
    • 适应性自旋
      • 自旋锁,多处理器上,一个线程请求资源被上锁,可以占用CPU自旋(忙循环),避免线程切换。
      • 适应性自旋意味着自旋时间不是固定的,由前一次在同一个锁上的自旋时间及锁拥有者的状态来决定。
    • 锁消除
      • 对不可能存在数据竞争的代码进行锁消除
    • 锁粗化
      • 如果虚拟机探测到一连串的对象都涉及到一个锁,可以将锁扩展到这个操作序列的外部。
    • 轻量级锁
      • 传统锁使用互斥量来实现
      • 轻量级锁通过CAS,对象头信息中的锁标志位实现。如果存在竞争关系,轻量级锁会膨胀为重量级锁。
    • 偏向锁
      • 消除数据在无竞争情况下的同步原语。

MySQL锁

锁是计算机协调多个进程或线程并发访问某一资源的机制。锁保证数据并发访问的一致性、有效性;锁冲突也是影响数据库并发访问性能的一个重要因素。锁是Mysql在服务器层和存储引擎层的的并发控制。

加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否是否已解除、释放锁等。

设计模式

详解java设计模式

Semphore

限制线程并发的数量

Exchanger

在两个线程之间传输数据

-------------本文结束 感谢您的阅读-------------
作者GonewithGt
有问题请 留言 或者私信我的 微博
满分是10分的话,这篇文章你给几分