偏向锁、轻量级锁、重量级锁的介绍

三种锁的特点

偏向锁

偏向锁适用于只有一个线程访问同步块的情况。偏向锁只有出现竞争条件时才会释放锁。并且撤销锁的时候需要等到全局安全点(这个时间点没有正在执行的字节码)。通过对对象头的修改从而把锁的状态改成无锁状态或者标记成不适合使用偏向锁。然后唤醒想要竞争锁的线程。

轻量级锁

轻量级锁会在同步代码块结束后释放锁。如果出现多线程竞争锁的情况,会通过自旋的方式来循环请求获取锁。如果获取锁失败,则会膨胀成重量级锁。因为自旋会消耗CPU这样会浪费一定的资源。但是响应速度大大提高。

重量级锁

出现线程竞争时不采用自旋的方式,而是阻塞线程。这样吞吐量会得到提高。

处理器实现原子操作

处理器会保证基本的内存操作的原子性。即保证从内存中读取或者写入一个字节是原子性的。当遇到复杂情况时,处理器提供了两种方式来保证复杂内存操作的原子性。

总线锁

当多个线程进行读改写操作时(i++)。由于不同线程可以从各自的缓存中读取i的值,进行+1操作后再分别写内存。这样i++的原子性就得不到保证。而总线锁可以保证当一个线程访问共享资源时,其他线程不能操作缓存了该共享变量内存地址的缓存。但是这样的话会导致其他并发线程所有访问内存的请求被阻塞。

缓存锁

缓存锁和总线锁的区别是,每次只需要锁住缓存行。而其他并行的线程还可以访问不是该缓存行缓存的内存的内容。

当访问的共享数据跨越多个缓存行或者共享数据不允许缓存时无法使用缓存锁只能通过总线锁来保证复杂内存操作的原子性。

java中实现操作的原子性

java中通过CAS和加锁的方式来保证操作的原子性。

猜你喜欢

转载自blog.csdn.net/qq_30033509/article/details/111932801