[锁 Lock] Lock lock = new ReentrantLock()之自增序列号 ╰半夏微凉° 2023-10-01 07:37 1阅读 0赞 **目录** 前言: 用锁的最佳实践: tryLock的同胞兄弟之 tryLock时间控制返回大师 tryLock(long time, TimeUnit unit): 使用介绍场景: 一般情况下的tryLock的使用场景: 额外技术小知识: ReentrantLock 与 synchronized tryLock 和 lock 和 lockInterruptibly 的区别 -------------------- -------------------- ## 前言: ## 我们有一个业务场景,必须生成唯一的自增序列号(作为订单号,订单号的组成是 区县+年月日+后8位序列号,这里的序列号我们使用了 前缀, 例如自增为1的时候 后8位显示为 00000001), ## 用锁的最佳实践: ## 1. **永远只在更新对象的成员变量时加锁;** 2. **永远只在访问可变的成员变量时加锁;** 3. **永远不在调用其他对象的方法时加锁。** ### **tryLock的同胞兄弟之 tryLock时间控制返回大师** tryLock(long time, TimeUnit unit)**:** ### tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的, 只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。 ### 使用介绍场景: ### tryLock 是防止自锁的一个重要方式。 `//学习 tryLock` tryLock()方法是有返回值的,返回值是Boolean类型。它表示的是用来尝试获取锁:成功获取则返回true;获取失败则返回false,这个方法无论如何都会立即返回。不会像synchronized一样,一个线程获取锁之后,其他锁只能等待那个线程释放之后才能有获取锁的机会。 #### 一般情况下的tryLock的使用场景: #### 我这里是用来 控制自增订单号生成使用的, 防止多线程去 请求 > Lock lock = new ReentrantLock(); > boolean b = lock.tryLock(); > > if(b){ > try { > > //处理任务 > > }finally { > //当获取锁成功时最后一定要记住finally去关闭锁 lock.unlock(); //释放锁 > lock.unlock(); > } > }else { > //else时为未获取锁,则无需去关闭锁 //如果不能获取锁,则直接做其他事情 也可以返回为null > return null; > } > > 第二种 抛出异常写法: > > if(b) \{ > try\{ > //处理任务 > \}catch(Exception ex)\{ > > \}finally\{ > //当获取锁成功时最后一定要记住finally去关闭锁 > lock.unlock(); //释放锁 > \} > \}else \{ > //else时为未获取锁,则无需去关闭锁 > //如果不能获取锁,则直接做其他事情 > \} > ## 额外技术小知识: ## #### ReentrantLock 与 synchronized #### 1. ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作,与 synchronized 会 被 JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出 现异常而无法正常解锁的情况,使用 ReentrantLock 必须在 finally 控制块中进行解锁操 作。 2. ReentrantLock 相比 synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要 使用 ReentrantLock。 #### tryLock 和 lock 和 lockInterruptibly 的区别 #### 1. tryLock 能获得锁就返回 true,不能就立即返回 false,tryLock(long timeout,TimeUnit unit),可以增加时间限制,如果超过该时间段还没获得锁,返回 false 2. lock 能获得锁就返回 true,不能的话一直等待获得锁 3. lock 和 lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程, lock 不会抛出异常,而 lockInterruptibly 会抛出异常。
还没有评论,来说两句吧...