Redis专题(3):锁的基本概念到Redis分布式锁实现

拓展阅读:Redis闲谈(1):构建知识图谱

Redis专题(2):Redis数据结构底层探秘

近来,分布式的问题被广泛提及,比如分布式事务、分布式框架、ZooKeeper、SpringCloud等等。本文先回顾锁的概念,再介绍分布式锁,以及如何用Redis来实现分布式锁。

一、锁的基本了解

首先,回顾一下我们工作学习中的锁的概念。

为什么要先讲锁再讲分布式锁呢?

我们都清楚,锁的作用是要解决多线程对共享资源的访问而产生的线程安全问题,而在平时生活中用到锁的情况其实并不多,可能有些朋友对锁的概念和一些基本的使用不是很清楚,所以我们先看锁,再深入介绍分布式锁。

在这里插入图片描述

通过一个卖票的小案例来看,比如大家去抢dota2 ti9门票,如果不加锁的话会出现什么问题?此时代码如下:

package Thread;

import java.util.concurrent.TimeUnit;

public class Ticket {

    /**
     * 初始库存量
     * */
    Integer ticketNum = 8;

    public void reduce(int num){
        //判断库存是否够用
        if((ticketNum - num) >= 0){
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            ticketNum -= num;
            System.out.println(Thread.currentThread().getName() + "成功卖出"
            + num + "张,剩余" + ticketNum + "张票");
        }else {
            System.err.println(Thread.currentThread().getName() + "没有卖出"
                    + num + "张,剩余" + ticketNum + "张票");
        }
    }

    public static void main(String[] args) throws InterruptedException{
        Ticket ticket = new Ticket();
        //开启10个线程进行抢票,按理说应该有两个人抢不到票
        for(int i=0;i<10;i++){
            new Thread(() -> ticket.reduce(1),"用户" + (i + 1)).start();
        }
        Thread.sleep(1000L);
    }

}

代码分析:这里有8张ti9门票,设置了10个线程(也就是模拟10个人)去并发抢票,如果抢成功了显示成功,抢失败的话显示失败。按理说应该有8个人抢成功了,2个人抢失败,下面来看运行结果:

在这里插入图片描述

我们发现运行结果和预期的情况不一致,居然10个人都买到了票,也就是说出现了线程安全的问题,那么是什么原因导致的呢?

原因就是多个线程之间产生了时间差

如图所示,只剩一张票了,但是两个线程都读到的票余量是1,也就是说线程B还没有等到线程A改库存就已经抢票成功了。

在这里插入图片描述

怎么解决呢?想必大家都知道,加个synchronized关键字就可以了,在一个线程进行reduce方法的时候,其他线程则阻塞在等待队列中,这样就不会发生多个线程对共享变量的竞争问题。

举个例子

比如我们去健身房健身,如果好多人同时用一台机器,同时在一台跑步机上跑步,就会发生很大的问题,大家会打得不可开交。如果我们加一把锁在健身房门口,只有拿到锁的钥匙的人才可以进去锻炼,其他人在门外等候,这样就可以避免大家对健身器材的竞争。代码如下:

public  synchronized void reduce(int num){
        //判断库存是否够用
        if((ticketNum - num) >= 0){
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值