分布式锁入门

前言:或许经常会听到分布式集群情况下,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
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值