前言:或许经常会听到分布式集群情况下,JVM锁会失效。那么为什么分布式情况下synchronized会失效呢?
一、那么首先我们需要弄清楚什么是线程锁,什么是进程锁,什么分布式锁。
线程锁:主要是用来给方法,代码块加锁。对同一时刻仅有同一线程执行改方法或代码块。线程锁只在同一JVM有效果,因为线程的实现在根本上是依靠线程之间共享内存实现的,比如synchronized实在共享对象头,显示锁Lock是共享某个变量
进程锁,为了控制同一操作系统多个进程访问某个共享资源,划重点(因为每个进程具有独立性,各个进程无法访问其他进程资源,因此synchronized失效。)
分布式锁:当多个进程在不同的系统中,用分布式锁控制多个进程对资源访问。
二、使用场景:
多JVM情况下才会采用,一般单体架构,一个jvm是完全没必要采用分布式锁,这样很耗资源
三、分布式锁的实现(Redis)
1,代码
/**
* 锁库
*/
suspend fun lockStock(apiMdStockLockParam: ApiMdStockLockParam) {
if (RedissLockUtil.tryLock(SystemConst.STOCK_LOCK_KEY,20,23)){
try {
doMapperTra (SystemConst.account){
MdOtherUserService.checkOtherUser(apiMdStockLockParam.otherName,apiMdStockLockParam.otherPassword,this)
apiMdStockLockParam.list.forEach {param ->
val mdStock = oGetMapper<MdStockMapper>().selectOne {
eq(MdStock::inventoryId,param.inventoryId)
eq(MdStock::delFlag,0)
}.oNl("即时库存id不存在")
if (mdStock.availableQty!!.compareTo(param.number) ==-1) throw RuntimeException("库存不足")
if (param.number.compareTo(BigDecimal.ZERO)<1) throw RuntimeException("锁库数量应大于0")
oGetMapper<MdStockMapper>().updateBy(
MdStock(
baseLockQty = mdStock.baseLockQty!!.add(param.number),
availableQty = mdStock.availableQty!!.subtract(param.number)
)){
eq(MdStock::mdStockId,mdStock.mdStockId)
}
}
}
}finally {
RedissLockUtil.unlock(SystemConst.STOCK_LOCK_KEY)
}
}else{
throw RuntimeException("锁库等待超时")
}
}
2.工具类:
package com.cloudinward.ynmd.config.redisson
import org.redisson.api.RLock
import org.redisson.api.RedissonClient
import org.slf4j.LoggerFactory
import java.util.concurrent.TimeUnit
object RedissLockUtil {
private val log = LoggerFactory.getLogger(RedissLockUtil::class.java)
private var redissonClient: RedissonClient = redisson
/**
* 加锁
* @param lockKey
* @return
*/
fun lock(lockKey: String): RLock {
val lock = redissonClient.getLock(lockKey)
lock.lock()
return lock
}
/**
* 释放锁
* @param lockKey
*/
fun unlock(lockKey: String) {
try {
val lock = redissonClient.getLock(lockKey)
lock.unlock()
} catch (e: Exception) {
log.error("释放锁:$lockKey 错误", e)
}
}
/**
* 释放锁
* @param lock
*/
fun unlock(lock: RLock) {
lock.unlock()
}
/**
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位:秒
*/
fun lock(lockKey: String, timeout: Int): RLock {
val lock = redissonClient.getLock(lockKey)
lock.lock(timeout.toLong(), TimeUnit.SECONDS)
return lock
}
/**
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
fun lock(lockKey: String, unit: TimeUnit, timeout: Int): RLock {
val lock = redissonClient.getLock(lockKey)
lock.lock(timeout.toLong(), unit)
return lock
}
/**
* 尝试获取锁
* @param lockKey 时间单位秒
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
fun tryLock(lockKey: String, waitTime: Int, leaseTime: Int): Boolean {
val lock = redissonClient.getLock(lockKey)
try {
return lock.tryLock(waitTime.toLong(), leaseTime.toLong(), TimeUnit.SECONDS)
} catch (e: InterruptedException) {
return false
}
}
/**
* 尝试获取锁
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
fun tryLock(lockKey: String, unit: TimeUnit, waitTime: Int, leaseTime: Int): Boolean {
val lock = redissonClient.getLock(lockKey)
try {
return lock.tryLock(waitTime.toLong(), leaseTime.toLong(), unit)
} catch (e: InterruptedException) {
return false
}
}
}
236





