java锁学习总结

1.乐观锁和悲观锁

乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为
别人不会修改,所以不会上锁, 但是在更新的时候会判断一下在此期间别人有没有去更新这个数
据,采取在写时先读出当前版本号,然后加锁操作。
悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人
会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁。java中的悲观锁就是synchronized
2.自旋锁
如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁
的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),
等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。
线程自旋是需要消耗 cup 的,说白了就是让 cup 在做无用功 ,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升
3. ReentrantLock 和 synchronized
 synchronized可以把任意一个非null的对象当成锁,他属于独占、悲观、可重入锁。
 synchronized作用的范围:
        1.方法 :锁住对象实例(this)
        2.静态方法 :锁住的是class实例的方法
        3.对象:锁住的是以该对象为锁的代码块。
ReentrantLock:
ReentantLock 继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完 成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等
避免多线程死锁的方法。
区别:
1.ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作,与 synchronized 会
被 JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出
现异常而无法正常解锁的情况,使用 ReentrantLock 必须在 finally 控制块中进行解锁操
2.ReentrantLock 相比 synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要
使用 ReentrantLock。
4.ReentrantLock中 tryLock,lock,lockInterruptibly区别
        1.tryLock 能获得锁就返回 true,不能就立即返回 false,tryLock(long timeout,TimeUnit
unit),可以增加时间限制,如果超过该时间段还没获得锁,返回 false
        2.lock 能获得锁就返回 true,不能的话一直等待获得锁
        3.lock 和 lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,
lock 不会抛出异常,而 lockInterruptibly 会抛出异常。
5.公平锁和不公平锁
公平锁: 加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
非公平锁:加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待
1. 非公平锁性能比公平锁高 5~10 倍,因为公平锁需要在多核的情况下维护一个队列
2. Java 中的 synchronized 是非公平锁,ReentrantLock 默认的 lock()方法采用的是非公平锁。

6.共享锁和独占锁

独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock 就是以独占方式实现的互斥锁。
共享锁则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock
7.ReadWriteLock 读写锁
为了提高性能,Java 提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制,如
果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。
8.可重入锁
就是一个线程在获取了锁之后,再次去获取了同一个锁,这时候仅仅是把状态值进行累加。
9.分布式锁实现方案
1.基于数据实现分布式锁: 操作数据库效率低,阻塞,自旋需要自己实现。
2.基于zookeeper实现分布式锁:基于临时节点实现,动态创建和删除节点需要自己实现。
3.基于redis实现分布式锁:Redisson框架实现锁的等待,自旋 ,锁的释放。
10.redis分布式实现
 1.jedis  
        加锁使用jedis.set()  需要保证set key和设置过期时间原子性操作。解锁 需要先判断锁是否是其本身,然后在解锁 使用 lua脚本保证原子性操作。
 2.redission
  加锁:使用lua脚本的原子性进行加锁
RLock rLock = this.redisson.getLock(lockKey);
rLock.tryLock((long)waitTimeout, 600L, TimeUnit.SECONDS); 
重要参数 key,uuid,waitTimeout,exprTime(过期时间)   uuid RLock类中已帮我们生成好了

解锁: 通过lua脚本的原子性操作进行解锁
RLock rLock = this.redisson.getLock(mutex.getLockKey());
rLock.unlock(); 
参数:key,uuid(加锁时的id)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值