锁实现互斥同步

同步是指多个线程并发访问共享数据时,保证同一时刻只有一个线程使用

java中,最近简单互斥锁实现使用synchronized关键字

synchronized关键字进过编译后,会在代码块前后生成一个monitor enter指令

以及多个monitor exit。保证异常情况下,能正常退出方法块

同时java中的ReentrantLock类也提供了同步功能,但是他同时还提供了很多高级功能例如:

等待可中断,可实现公平锁,以及锁绑定多个条件,锁过期

公平锁:按照申请锁的时间顺序依次获取锁

synchronzied:非公平锁  ReentrantLock:默认非公平锁,可配置公平锁

建议:jdk1.6以后优先考虑使用synchronzied实现互斥同步

非阻塞同步

互斥同步会进行线程阻塞和唤醒,同时带来性能问题,被称为阻塞同步(悲观并发策略)

数据共享产生争用,产生冲突,采取补偿措施,不把线程挂起,被称为非阻塞同步(乐观并发策略)

非阻塞同步实现CAS,CAS指令执行时,只有内存地址值等于旧预期值时,处理才会将内存地址值更新

缺点:会出现ABA问题,java提供了AtomicStampedReference通过版本控制变量值,来保证CAS的正确性。

如果出现ABA问题,传统互斥锁性能可能比原子类性能更好

无同步方案

ThreadLocal:线程本地存储,保证变量的可见性,再同一个线程中,是一种无锁化实现。

使用场景:springmvc中单例模式下,保证高并发线程安全。

重量级锁

重量级锁会阻塞加锁失败的线程,在目标锁被释放后,重新唤醒进程

java线程的阻塞和唤醒,是由操作系统来完成的,涉及用户态与内核态切换,开销非常大

为了避免昂贵的阻塞和唤醒,java引入自适应自旋,其实实质在处理器中空跑一段时间,等待锁释放

轻量级锁

轻量级锁,jdk1.6引入通过CAS操作,当前比较对象锁字段的值是否为当前锁记录的地址,如果成功该线程获取到对象。

CAS不成功,检查锁对象是否指向当前的栈帧

如果是jvm会清除锁,进入该同步块,否则证明锁被其他线程持有,超过2个争用该锁会被膨胀为重量级锁

java锁机制-LMLPHP

偏向锁

偏向锁是在在无竞争情况下,去除同步和CAS操作,偏向获得他的第一个线程

jdk1.6开始默认,通过-XX:+UseBaisedLocking设置

锁类型的变化过程如下图:

java锁机制-LMLPHP

04-26 21:56