基于redis实现的分布式锁

我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源。锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标识,因此基于redis实现的分布式锁主要依赖redis的SETNX命令和DEL命令,SETNX相当于上锁,DEL相当于释放锁,当然,在下面的具体实现中会更复杂些。之所以称为分布式锁,是因为客户端可以在redis集群环境中向集群中任一个可用Master节点请求上锁(即SETNX命令存储key到redis缓存中是随机的)。

现在相信你已经对在基于redis实现的分布式锁的基本概念有了解,需要注意的是,这个和前面文章提到的使用WATCH 命令对key值进行锁操作没有直接的关系。java中synchronized和Lock对象都能对共享资源进行加锁,下面我们将学习用java实现的redis分布式锁。

java中的锁技术

在分析java实现的redis分布式锁之前,我们先来回顾下java中的锁技术,为了直观的展示,我们采用“多个线程共享输出设备”来举例。

不加锁共享输出设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class LockTest {
    //不加锁
    static class Outputer {
        public void output(String name) {
            for(int i=0; i<name.length(); i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println();
        }
    }
    public static void main(String[] args) {
        final Outputer output = new Outputer();
        //线程1打印zhangsan
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true) {
                     try{
                         Thread.sleep(1000);
                     }catch(InterruptedException e) {
                         e.printStackTrace();
                     }
                     output.output("zhangsan");
                }  
            }
        }).start();
         
        //线程2打印lingsi
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true) {
                     try{
                         Thread.sleep(1000);
                     }catch(InterruptedException e) {
                         e.printStackTrace();
                     }
                     output.output("lingsi");
                }
            }
        }).start();
         
        //线程3打印wangwu
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true) {
                     try{
                         Thread.sleep(1000);
                     }catch(InterruptedException e) {
                         e.printStackTrace();
                     }
                     output.output("huangwu");
                }
            }
        }).start();
    }
}

上面例子中,三个线程同时共享输出设备output,线程1需要打印zhangsan,线程2需要打印lingsi,线程3需要打印wangwu。在不加锁的情况,这三个线程会不会因为得不到输出设备output打架呢,我们来看看运行结果:

1
2
3
4
5
6
7
8
9
10
11
huangwu
zhangslingsi
an
huangwu
zlingsi
hangsan
huangwu
lzhangsan
ingsi
huangwu
lingsi

  

从运行结果可以看出,三个线程打架了,线程1没打印完zhangsan,线程2就来抢输出设备......可见,这不是我们想要的,我们想要的是线程之间能有序的工作,各个线程之间互斥的使用输出设备output。

http://www.cnblogs.com/hjwublog/p/5749929.html

https://my.oschina.net/91jason/blog/517996?p=1

基于redis实现的分布式锁的更多相关文章

  1. 基于Redis的简单分布式锁的原理

    参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...

  2. 一个Redis实现的分布式锁

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...

  3. redis客户端、分布式锁及数据一致性

    Redis Java客户端有很多的开源产品比如Redission.Jedis.lettuce等. Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持:Redis ...

  4. 基于zookeeper实现高性能分布式锁

    实现原理:利用zookeeper的持久性节点和Watcher机制 具体步骤: 1.创建持久性节点 zkLock 2.在此父节点下创建子节点列表,name按顺序定义 3.Java程序获取该节点下的所有顺 ...

  5. Redis系列(二)--分布式锁、分布式ID简单实现及思路

    分布式锁: Redis可以实现分布式锁,只是讨论Redis的实现思路,而真的实现分布式锁,Zookeeper更加可靠 为什么使用分布式锁: 单机环境下只存在多线程,通过同步操作就可以实现对并发环境的安 ...

  6. redis系列:分布式锁

    redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  7. Redis高并发分布式锁详解

    为什么需要分布式锁 1.为了解决Java共享内存模型带来的线程安全问题,我们可以通过加锁来保证资源访问的单一,如JVM内置锁synchronized,类级别的锁ReentrantLock. 2.但是随 ...

  8. 基于redis的简易分布式爬虫框架

    代码地址如下:http://www.demodashi.com/demo/13338.html 开发环境 Python 3.6 Requests Redis 3.2.100 Pycharm(非必需,但 ...

  9. 基于zookeeper实现的分布式锁

    基于zookeeper实现的分布式锁 2011-01-27 • 技术 • 7 条评论 • jiacheo •14,941 阅读 A distributed lock base on zookeeper ...

随机推荐

  1. 重学C++ (1)

    写在开头的话:这学期没有写太多的代码,终于把中英文两篇论文弄完了,趁着中间的空隙,想想找工作的处境.自己也定了自己的方向.不管学什么语言吧,每个语言都有自己的优势和使用的群体.只要自己是良马,终会有伯 ...

  2. 0-1背包问题与N皇后问题的纠结

    昨日同学要我帮他看一道算法,如下: 是不是乍一看是“0-1背包”问题呀,我也这么想,于是就这么兴致勃勃的开始用这个想法去思考怎么算.但是算法也忘得差不多,回去赶紧补补,也趁着这次机会好好复习一下算法, ...

  3. Spring零碎知识复习

    自学了Spring也有一段时间了,多多少少掌握了一些Spring的知识,现在手上也没有很多的项目练手,就将就着把这些学到的东西先收集起来,方便日后用到的时候没地方找. 1.spring的国际化 主要是 ...

  4. oracle pl/sql的操作大全

    --删除该用户及下面的所有关联 DROP USER fspdrs CASCADE; --创建一个用户 create user fspdrs identified " default tabl ...

  5. DTcms会员中心添加新页面-会员投稿,获得所有文章并分页

    DAL.article.cs /// <summary> /// 自定义:获得查询分页数据 /// </summary> public DataSet GetList(int ...

  6. Arcgis 10.1 求面里面所包含的点的平均值

    空间链接的作用:将面上的所有点的值加起来取平均值。赋值给面属性。(我们可以定义右击——定义合并规则 连接要素的字段映射参数中指定的合并规则仅适用于连接要素中的属性,且仅适用于多个要素与目标要素匹配   ...

  7. RecursiveDirectoryIterator目录操作类

    /** * @author Funsion Wu * @abstract SPL使用案例,全国首发,技术分享,欢迎转帖 */ class Dir extends RecursiveDirectoryI ...

  8. php 如何开启session

    1.如果你在session_start()前没有输出内容,哪怕是一个句号也不行,就可以直接使用session_start)_; 2.如果你之前已经有输出内容了,可以使用以下方法: <?php o ...

  9. c#对字符串的各种操作

    1.字符串定义 2.在字符串后面追加字符串 3.获取字符串长度 4.截取字符串的一部分 5.字符串转为比特码 6.查指定位置是否为空字符 7.查字符串是否是标点符号 8.截头去尾(Trim) 9.替换 ...

  10. 【BZOJ1030】文本生成器

    Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是 ...