千家信息网

Redis中锁的介绍和使用

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,其实说多线程修改数据也不合适,毕竟redis服务端是单线程的,所有命令串行执行,只是在客户端并发发送命令的时候,导致串行的命令一些排列问题和网络时间差等造成数据不一致。本文虽然是数字的加减,但是为了说
千家信息网最后更新 2026年11月03日Redis中锁的介绍和使用

其实说多线程修改数据也不合适,毕竟redis服务端是单线程的,所有命令串行执行,只是在客户端并发发送命令的时候,导致串行的命令一些排列问题和网络时间差等造成数据不一致。本文虽然是数字的加减,但是为了说明锁的情况,故意不是用原子命令incr。

先配上一个简易的RedisHelper,一个set值,一个get值,一个设置并发锁,以便在我后面的操作中,你能清楚我究竟做了什么。

public class RedisHelper    {        public RedisClient client = new RedisClient("127.0.0.1", 6379);        public void Set(string key, T val)        {            client.Set(key, val);        }        public T Get(string key)        {            var result = client.Get(key);            return result;        }        public IDisposable Acquire(string key)        {           return  client.AcquireLock(key);        }    }

下面看一下并发代码,我只new了两个Thread。两个线程同时想访问同一个key,分别访问五万次,在并发条件下,我们很难保证数据的准确性,请比较输出结果。

static void Main(string[] args)        {            RedisHelper rds = new RedisHelper();            rds.Set("mykey1", 0);            Thread myThread1 = new Thread(AddVal);            Thread myThread2 = new Thread(AddVal);            myThread1.Start();            myThread2.Start();            Console.WriteLine("等待两个线程结束");            Console.ReadKey();        }        public static void AddVal()        {            RedisHelper rds = new RedisHelper();            for (int i = 0; i < 50000; i++)            {                                    int result = rds.Get("mykey1");                    rds.Set("mykey1", result + 1);                            }            Console.WriteLine("线程结束,输出" + rds.Get("mykey1"));        }

是的,和我们单线程,跑两个50000,会输出100000。现在是两个并发线程同时跑在由于并发造成的数据结果往往不是我们想要的。那么如何解决这个问题呢,Redis已经为我们准备好了!

你可以看到我RedisHelper中有个方法是 public IDisposable Acquire(string key)。 也可以看到他返回的是IDisposable,证明我们需要手动释放资源。

方法内部的 AcquireLock正是关键之处,它像redis中索取一把锁头,被锁住的资源,只能被单个线程访问,不会被两个线程同时get或者set,这两个线程一定是交替着进行的,当然这里的交替并不是指你一次我一次,也可能是你多次,我一次,下面看代码。

static void Main(string[] args)        {            RedisHelper rds = new RedisHelper();            rds.Set("mykey1", 0);            Thread myThread1 = new Thread(AddVal);            Thread myThread2 = new Thread(AddVal);            myThread1.Start();            myThread2.Start();            Console.WriteLine("等待两个线程结束");            Console.ReadKey();        }        public static void AddVal()        {            RedisHelper rds = new RedisHelper();            for (int i = 0; i < 50000; i++)            {                using (rds.Acquire("lock"))                {                    int result = rds.Get("mykey1");                    rds.Set("mykey1", result + 1);                }            }            Console.WriteLine("线程结束,输出" + rds.Get("mykey1"));        }

可以看到我使用了using,调用我的Acquire方法获取锁。

输出结果最后是100000,正是我们要的正确结果。前面的8W+是因为两个线程之一先执行结束了。

还有,在正式使用的过程中,建议给我们的锁,使用后删除掉,并加上一个过期时间,使用expire。

以免程序执行期间意外退出,导致锁一直存在,今后可能无法更新或者获取此被锁住的数据。

你也可以尝试一下不设置expire,在程序刚开始执行时,关闭console,重新运行程序,并且在redis-cli的操作控制台,get你锁住的值,将会永远获取不到。

所有连接此redis实例的机器,同一时刻,只能有一个获取指定name的锁.

下面是StackExchange.Redis的写法

var info = "name-"+Environment.MachineName;            //如果5秒不释放锁 自动释放。避免死锁            if (db.LockTake("name", info, TimeSpan.FromSeconds(5)))            {                try                {                                   }                catch (Exception ex)                {                                    }                finally                {                                       db.LockRelease("name", token);                }            }

以上就是Redis锁的简单应用介绍的详细内容,更多请关注其它相关文章!

线程 两个 数据 输出 命令 结果 同时 方法 程序 代码 时间 资源 问题 合适 清楚 一致 意外 关键 写法 准确性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京路客互联网科技有限公司 互联网科技官网 互联网下的科技发展 电子科技大学互联网 兼蜜互联网科技 深圳期待互联网科技 互联网科技大会 佩信高科技互联网 衡水科技产业互联网平台 山东吉时兔互联网科技有限公司 昭通云南众福互联网科技有限公司 米聚互联网科技南京有限公司排面 互联网科技扶贫时间 互联网新科技动漫ppt素材 深圳市罗太互联网科技有限公司 云南省自由互联网科技有限公司 互联网科技手机排行榜 北京军民互联网科技公司 互联网科技的前景 互联网科技大会大佬 撒么互联网科技公司 顶级互联网科技成果有哪些 成都铂石互联网科技做什么的 江阴互联网智能科技产品进口 互联网科技与大数据专业 恒生互联网科技指数跳水 工业互联网等科技实现智能化赋能 伊宁互联网科技做什么的 互联网营销推广黑科技 富国互联网金融科技混合基金
0