美文网首页
记录一次并发引起的分布式锁问题

记录一次并发引起的分布式锁问题

作者: 多关心老人 | 来源:发表于2023-04-06 19:06 被阅读0次

项目中使用了线程池处理设备上报的数据,为了保证数据不乱序,每个设备的数据用固定的线程处理。

for (int i = 0; i < executorCount; i++) {
//            必须单线程运行
            ExecutorService executor = new ThreadPoolExecutor(1, 1, 10, TimeUnit.MINUTES, new LinkedBlockingDeque<>(1024),
                    new NamedThreadFactory("energy-efficiency-g" + i, null, true, (Thread t, Throwable e) -> {
                        log.error("处理XXX发生异常", e);
                    }),
                    new ThreadPoolExecutor.DiscardOldestPolicy(){
                        @Override
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                            log.error("线程池已满,触发拒绝策略,请考虑扩大线程池或者使用集群");
                            super.rejectedExecution(r, e);
                        }
                    });
            executors[i] = executor;
        }

由于每个ThreadPoolExecutor中的线程数就1个,因此线程名应该是"energy-efficiency-g1-1"这种,后缀名一定是1,在项目运行过程中,发现后缀不是1而是其他数字,当时并未注意。

现在在线程处理业务的时候加了分布式锁,竟然加锁失败。锁的key是设备的mac,如果按照理想的情况,每个mac都是固定线程在处理,因此每个设备的数据都会在queue里排队等待处理,不会出现一个设备的两包数据争抢一把锁,在debug的时候,发现一直在创建线程即下面的代码一直触发

new NamedThreadFactory("energy-efficiency-g" + i, null, true, (Thread t, Throwable e) -> {
                        log.error("处理XXX发生异常", e);
                    }),

至于为什么没发现报错日志,是因为这个log输出到另一个文件了,没及时发现。

回到问题本身:为什么会一直创建线程呢?


image.png

如果队列中有任务或者没线程没闲置很久,那么就一直在while循环里,那可能就是task.run()抛异常了,打上断点确实抛异常了,原来是在task中获取分布式锁后设置看门狗的时候因为代码版本原因报错了,这里throw x导致跳出while循环,进入后面的


image.png
在这里又会创建一个新的Worker(Thread),而新的Thread又会去queue里取任务去执行去加分布式锁,这个时候原先的线程还没执行完毕,锁也没释放,因此新线程再获取分布式锁就失败了。

相关文章

  • java锁的概念

    参考文档探究分布式并发锁并发编程-锁的发展和主流分布式锁比较总结从构建分布式秒杀系统聊聊分布式锁探索并发编程(六)...

  • 关于Redis分布式锁安全性的思考(上)

      分布式应用进行逻辑处理时经常会遇到并发问题,这个时候就要使用到分布式锁来限制程序的并发执行。分布式锁的实现方式...

  • etcd:一款比Redis更骚的分布式锁的实现方式!用它

    分布式锁 关于为什么要有分布式****锁这个东西,欢迎阅读我的zk分布式锁的实现,介绍了单机高并发、分布式高并发的...

  • 分布式锁与事务之间不可不描述的事情-锁间隙问题

    在考虑使用分布式锁时,你还在为并发时的性能问题考虑吗? 还在为使用zk来实现分布式锁还是redis实现分布式锁而烦...

  • 分布式锁及分布式事务

    分布式锁是解决并发时资源争抢的问题,分布式事务和本地事务是解决流程化提交问题。一、其中分布式锁实现:1.基于数据库...

  • Redis读书笔记

    Redis分布式锁 1.分布式应用进行逻辑处理时经常会遇到并发问题。为了保持系统操作原子性,需要进行分布式锁的使用...

  • 分布式锁实现

    在多实例部署中,当我们需要对实例间作并发控制,那么就涉及分布式锁问题,我们常用的分布式锁实现有基于 Redis /...

  • 关于iOS线程锁的一点研究

    什么是锁 多线程中,对共享资源进行访问,为了防止并发引起的相关问题,通常都是引入锁的机制来处理并发问题。学术上对线...

  • 记录一次Java文件锁引起的并发写文件问题

    背景 刚接手新项目,该项目是高并发的游戏日志服务端存储,一个项目适配多个游戏,很多特殊需求要兼容,刚开始接手,需要...

  • MySQL悲观锁与乐观锁的实现方案

    我们知道Mysql并发事务会引起更新丢失问题,解决办法是锁,所以本文将对锁(乐观锁、悲观锁)进行分析 悲观锁和乐观...

网友评论

      本文标题:记录一次并发引起的分布式锁问题

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