多线程系列

java线程中的锁

2020-01-24  本文已影响0人  小蜗牛Aaron

java中的锁的概念

自旋锁: 是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
乐观锁: 假定没有冲突,在修改数据时如果发现数据和之前获取的不一致,则读最新数据,修改后重试修改。
悲观锁: 假定会发生并发冲突,同步所有对数据的相关操作,从读数据就开始上锁。
独享锁(写):给资源加上写锁,线程可以修改资源,其他线程不能再加锁; (单写)
共享锁(读): 给资源加上读锁后只能读不能改,其他线程也只能加读锁,不能加写锁; (多读)
可重入锁、不可重入锁: 线程拿到一把锁之后,可以自由进入同一把锁所同步的其他代码。
公平锁、非公平锁: 争抢锁的顺序,如果是按先来后到,则为公平。

同步关键字

1、用于实例方法、静态方法时,隐式指定锁对象
2、用于代码块时,显示指定锁对象
3、锁的作用域:对象锁、类锁、分布式锁
4、引申:如果是多个进程,怎么办?
特性: 可重入、独享、悲观锁
特殊优化 : 锁消除 (开启锁消除的参数:-XX:+DoEscapeAnalysis -XX:+EliminateLocks) 、锁粗化 JDK做了锁粗化的优化, 但我们自己可从代码层面优化

同步关键字的原理

默认情况下JVM锁会经历:未锁定->偏向锁 -> 轻量级锁 -> 重量级锁 这四个状态

轻量级锁

在未锁定的状态下,可以通过CAS来抢锁,抢到的是轻量级锁。


image.png

重量级锁

轻量级锁中的自旋有一定的次数限制,超过了次数限制,轻量级锁升级为重量级锁。


image.png

偏向锁

在JDK6 以后,默认已经开启了偏向锁这个优化,通过JVM 参数 -XX:-UseBiasedLocking 来禁用偏向锁若偏向锁开启,只有一个线程抢锁,可获取到偏向锁

锁升级的过程

image.png

偏向标记第一次有用,出现过争用后就没用了。 -XX:-UseBiasedLocking 禁用使用偏置锁定,偏向锁,本质就是无锁,如果没有发生过任何多线程争抢锁的情况,JVM认为就是单线程,无需做同步(jvm为了少干活:同步在JVM底层是有很多操作来实现的,如果是没有争用,就不需要去做同步操作)

重量级锁 - 监视器

修改mark word如果失败,会自旋CAS一定次数,该次数可以通过参数配置:超过次数,仍未抢到锁,则锁升级为重量级锁,进入阻塞

monitor也叫做管程,计算机操作系统原理中有提及类似概念。一个对象会有一个对应的monitor。

image.png

wait/notify机制

wait方法导致当前线程等待,加入该对象的等待集合中,并且放弃当前持有的对象锁。notify/notifyAll方法唤醒一个或所有正在等待这个对象锁的线程。
注意:
1、只能在synchronized关键字中使用,且调用wait、notify的对象与锁对象相同,否则会抛出IllegalMonitorStateException异常。
2、wait() 方法调用后,会破坏原子性。

锁的本质

场景:土豪小区车位紧张,只有0357车位还未出售 此时,此时大家都想买0357车位买了0357车位,才能在这儿停车 (加锁)跟小区签订合同后,你就具备了停车0357的资格就说你获得了锁会有一把车位锁,来象征你的0357车位停车资格。

locks包 类层次结构

image.png

void lock(); 获取锁(不死不休)
boolean tryLock(); 获取锁(浅尝辄止)
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 获取锁(过时不候)
void lockInterruptibly() throws InterruptedException; 获取锁(任人摆布)
void unlock(); 释放锁
Condition newCondition();
结论:
1、lock()最常用;
2、lockInterruptibly()方法一般更昂贵,有的impl可能没有实现lockInterruptibly(),
只有真的需要效应中断时,才使用,使用之前看看impl对该方法的描述。

Reentrantlock

image.png

Condition

用于替代wait/notify。
Object中的wait(),notify(),notifyAll()方法是和synchronized配合使用的,可以唤醒一个或者全部(单个等待集);
Condition是需要与Lock配合使用的,提供多个等待集合,更精确的控制(底层是park/unpark机制);


image.png

同步关键字VS lock

Synchronized

lock
优点:
1、所有synchronized的缺点
2、可以实现更多的功能,让synchronized缺点更多

ReadAndWrite Lock

维护一对关联锁,一个只用于读操作,一个只用于写操作;
读锁可以由多个读线程同时持有,写锁是排他的。同一时间,两把锁不能被不同线程持有。

适合读取操作多于写入操作的场景,改进互斥锁的性能,比如:集合的并发线程安全性改造、缓存组件。

锁降级指的是写锁降级成为读锁。持有写锁的同时,再获取读锁,随后释放写锁的过程。
写锁是线程独占,读锁是共享,所以写->读是降级。(读->写,是不能实现的)

上一篇 下一篇

猜你喜欢

热点阅读