美文网首页我爱编程
Java高并发编程之-分布式锁

Java高并发编程之-分布式锁

作者: AlbertJoy | 来源:发表于2018-06-21 16:15 被阅读0次

    什么是锁

    🔒

    计算机软件开发里面有许多关于锁的概念。如数据库中的:共享锁,排他锁。或者是应用程序中的:线程锁,进程锁。

    在Java多线程开发中也有关于锁的概念。

    在JDK的java.util.concurrent.locks包下面就有关于Java的锁的原生实现。

    那么究竟什么是锁了。

    为了在多线程程序中,在资源竞争的情况下,保证数据的安全性。就需要通过加锁互斥来保证。锁就是一个标识。在JDK的实现中,锁通常是存储在对象的头部来标识。

    为什要使用锁

    在多线程程序中,有一些资源对象可能被多线程程序的一个业务逻辑方法同时调用。那么我们称多线程的这个方法对这个资源对象存在着资源竞争。如果要保证这个资源对象的数据是安全的,就需要让多线程的这个方法互斥。这个是后就只用通过给资源对象加锁来实现。多线程的这个方法在去操作这个资源对象是需要先获取锁,在这个方法的业务逻辑执行完成后再释放锁。这样的多线程程序才是线程安全的。

    举个例子:有3个窗口售卖常德到长沙的100张火车票。这3个窗口就用3个线程来标识。如果不上锁,会出现什么状况了。

    我们来看下这个程序。

    如果方法没有加锁,我们发现会出现一票被多个窗口售卖的情况。这样我们的程序就出现bug了。为了防止多线程并发程序的bug。通常我们会使用synchronized关键字来实现同步方法。synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。也可以使用JDK的java.util.concurrent.locks包下面的ReentrantLock(可重入锁)来手动加锁和释放锁。推荐使用这中做法。

    什么是分布式锁

    在分布式的场景下,应用程序通常是运行在不同的机器上。这个时候,锁不能像多线程程序一样,存放在JVM给进程分配的内存区域的某个对象上。需要一个集中的中央存取区域。分布式系统中的每一个进程在获取锁和释放锁是都去访问这个集中的中央存取区域。在实际的开发过程中,这个用户存放分布式锁的存取区域可以是:数据库,Redis, Zookeeper, etcd, Tair,文件系统等。只要是一个集中的中央存取区域并且能用来做为标识,都可以来实现分布式锁。这里我们来介绍用Redis来实现一个分布式锁。


    为什么要用分布式锁

    随着Spring Cloud微服务架构的开源与流行,很多中小型公司也开始使用这一架构。所以很多新开发的应用都是分布式的。很多知名的大公司都有自己的微服务架构或是使用的开源架构。也就是说,除了单体应用外,分布式程序也占据了一定的市场份额。那么要在分布式应用程序中保证资源对象的安全,这时我们就应该使用分布式锁。

    举例:唯品会秒杀的超卖事件

    什么情况下使用分布式锁


    秒杀,抢红包等高并发的场景下。

    怎么实现一个分布式锁


    分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息,这时候我们很容易就想到了Redis。使用数据库,Redis, Zookeeper, etcd, Tair,文件系统等都能实现。这里我们介绍使用Redis的方式来实现一个分布式锁。

    使用的redis命令:

    set key value [EX seconds] [PX milliseconds] [NX|XX]

    如:set foo "process1" PX 3000 NX

    一些其他的redis命令:

    setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。

    get(key):获得key对应的value值,若不存在则返回nil。

    getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。

    expire(key, seconds):设置key-value的有效期为seconds秒。

    推荐使用redisson这个开源的库来实现基于redis的分布式锁。

    redisson

    总结

    相关文章

      网友评论

        本文标题:Java高并发编程之-分布式锁

        本文链接:https://www.haomeiwen.com/subject/rttcyftx.html