java虚拟机-线程安全与锁优化

2018-08-13  本文已影响9人  白六小子

当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。——Brain Goetz


一、java中的线程安全

多个线程之间存在共享数据竞争是线程安全解决问题的前提。
如果将线程安全归为非真即假的二元选项,按照线程安全的程度由强至弱,可以分为以下五类

二、常见的线程安全实现的方法

1. 互斥同步

何为同步?
多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个线程使用。
何为互斥?
互斥是实现同步的手段,临界区,互斥量,信号量都是主要的互斥实现方式。因此互斥是因,同步是果。互斥是方法,同步是目的。
如何实现同步互斥?
(1)synchronized
该关键字经过编译后会在同步块的前后分别形成moniterenter和monitorexit这两个字节码指令。

这两个字节码指令都需要一个reference类型的参数来指定要锁和解锁的对象。如果java程序中明确指明了这个对象参数,那就是这个对象的reference。如果没有明确指定,那就根据synchronized修饰的是实例方法还是类方法,去取对应的对象实例货class对象作为锁对象。
执行monitorenter时锁计数器加1,执行monitorexit时锁计数减1,锁计数器为0时就释放锁,如果获取锁失败就阻塞等待,知道对象锁被另外一个线程释放。

(2)ReentrantLock
lock和unlock配合try/finally使用

synchronized和reentrantlock两者都是可重入锁。
何为可重入锁?:一个线程或得了某对象锁后,后续执行该对象上的其他加锁方法不会阻塞而会直接获取锁,即一个线程获取锁的时候不会自己把自己锁死。 

(3)reentrantlock与synchronized的区别

两者性能并无多少差别,使用时以合适的场景和方便为主。

2. 无同步方案

(1)ThreadLocal
线程本地私有变量。是以map的形式存储变量Key—Value。其中key为当前变量,value为要存储的值。用数组来存储,本质上是拉链法来解决hash冲突。

上一篇下一篇

猜你喜欢

热点阅读