Java并发编程(-)基础

多线程一定快吗

由于线程有创建和上下文切换的开销,短时间的操作会比单线程更慢

如何减少上下文切换

  • 无锁并发编程:多线程竞争锁,会引发上下文切换,所以可以减少锁的使用,如,按照数据的ID按照Hash取模分段,不同的线程处理不同的段
  • CAS算法:Java的Atomic包使用这个来更新数据,不需要加锁
  • 使用最少线程:避免创建不需要的线程
  • 协程:单线程中实现多任务调度,在单线程中维持多任务间的切换

volatile

他在多处理器开发中保证了共享变量的“可见性”,可见性指当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。

为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存后进行操作,但操作完成不知道何时回写会内存,所以普通的操作会出现两个处理器的数据不一致的情况,而导致多线程数据不统一,这时候可以使用volatile。
volatile会做两件事情:

  1. 将当前处理器缓存的数据写回到系统内存中
  2. 这个写回内存的操作会使其他CPU里缓存了该内存地址的数据无效

synchronized

Java中的内一个对象都可以作为锁,

  • 对于普通同步方法,锁是当前实例对象
  • 对于静态同步方法,锁是当前类的Class对象
  • 对于同步方法块,锁是Synchronized括号里的对象

synchronized在JVM的实现原理,JVM进入和退出Monitor对象来实现方法同步和代码块的同步,包括monitorenter和monitorexit,在编译后插入的同步代码块的开始和结束或者异常的位置,JVM保证这两个是成对出现,当且一个monitor被持有后就锁定。
synchronized的锁是存在java对象头里的

原子操作

  • 总线锁
    两个处理器同时从各自的缓存中读取变量i,分别进行加1,然后写回系统内存,可能会出现覆盖写入的情况,结果不是3,而是2
    处理器使用总线锁可以处理:提供一个LOCK信号,当一个处理器在总线上输出此信号时,其他处理器的请求被阻塞,处理器可以独占共享内存。
    总线锁,锁住了所有的内存通信,开销太大。
  • 缓存锁
    内存区域如果被缓存在处理器缓存中,并且Lock操作期间被锁定,当他执行锁操作回写到内存是,处理器不在总线上声明lock,而是修改内部的内存地址,并允许他的缓存一致性机制来保证原子性。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章