深入理解与应用多线程技术( 三 )


  • 偏向锁:在无竞争的情况下,只是在Mark Word里存储当前线程指针,CAS操作都不做 。
  • 轻量级锁:在没有多线程竞争时,相对重量级锁,减少操作系统互斥量带来的性能消耗 。但是,如果存在锁竞争,除了互斥量本身开销,还额外有CAS操作的开销 。
  • 自旋锁:减少不必要的CPU上下文切换 。在轻量级锁升级为重量级锁时,就使用了自旋加锁的方式
  • 锁粗化:将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁 。
  • 锁消除:虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除 。
线程有哪些状态
深入理解与应用多线程技术

文章插图
图片
  • New:线程对象创建之后、但还没有调用start()方法 , 就是这个状态 。
  • Runnable:它包括就绪(ready)和运行中(running)两种状态 。如果调用start方法,线程就会进入Runnable状态 。它表示我这个线程可以被执行啦(此时相当于ready状态) , 如果这个线程被调度器分配了CPU时间,那么就可以被执行(此时处于running状态) 。
  • Blocked:阻塞的(被同步锁或者IO锁阻塞) 。表示线程阻塞于锁,线程阻塞在进入synchronized关键字修饰的方法或代码块(等待获取锁)时的状态 。比如前面有一个临界区的代码需要执行,那么线程就需要等待,它就会进入这个状态 。它一般是从RUNNABLE状态转化过来的 。如果线程获取到锁,它将变成RUNNABLE状态 。
  • WAITING : 永久等待状态,进入该状态的线程需要等待其他线程做出一些特定动作(比如通知) 。处于该状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态 。一般Object.wait 。
  • TIMED_WATING: 等待指定的时间重新被唤醒的状态 。有一个计时器在里面计算的 , 最常见就是使用Thread.sleep方法触发 , 触发后,线程就进入了Timed_waiting状态,随后会由计时器触发,再进入Runnable状态 。
  • 终止(TERMINATED):表示该线程已经执行完成 。
CountDownLatch与CyclicBarrier 区别CountDownLatch和CyclicBarrier都用于让线程等待,达到一定条件时再运行 。主要区别是:
  • CountDownLatch:一个或者多个线程,等待其他多个线程完成某件事情之后才能执行;
  • CyclicBarrier:多个线程互相等待,直到到达同一个同步点 , 再继续一起执行 。

深入理解与应用多线程技术

文章插图
图片
多线程环境下的伪共享
 
CPU的缓存是以缓存行(cache line)为单位进行缓存的 , 当多个线程修改相互独立的变量 , 而这些变量又处于同一个缓存行时就会影响彼此的性能 。这就是伪共享
现代计算机计算模型:
深入理解与应用多线程技术

文章插图
图片
  • CPU执行速度比内存速度快好几个数量级,为了提高执行效率,现代计算机模型演变出CPU、缓存(L1,L2,L3) , 内存的模型 。
  • CPU执行运算时,如先从L1缓存查询数据,找不到再去L2缓存找,依次类推,直到在内存获取到数据 。
  • 为了避免频繁从内存获取数据,聪明的科学家设计出缓存行,缓存行大小为64字节 。
也正是因为缓存行的存在 , 就导致了伪共享问题,如图所示:
深入理解与应用多线程技术

文章插图
图片
假设数据a、b被加载到同一个缓存行 。