当前位置: 首页 > news >正文

C#Queue<T>队列出现弹出元素被最后一次压入得元素覆盖的问题

问题代码:

//以下为现有代码的大概描述,只可意会,不可执行!!!Queue<Move> mQueue = new Queue<Move>();
//该接口为下面描述线程A、线程B调用的接口
private void ActionTrigger(Move move)//Move表示一个类,由外部传入
{lock(mlock){    this.DoMove1(move);//将move压入队列ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoMove2());//启用多线程将move弹出,并执行相关动作。}
}private void DoMove1(Move move)
{lock(mlockEn){mQueue.Enqueue(move);}
}private void DoMove2(object obj)
{lock(mlockDe){while(mQueue.Count>0){Move mtmp = mQueue.Dequeue();//通过打印mtmp地址、mtmp中变量指向的地址发现,出现问题时,连续添加的Move均被最后一个元素覆盖。//根据mtmp执行相关耗时动作}}
}

问题背景:

1.一个线程A不间断向Queue压入元素,压入元素后,会启动多线程进行元素弹出,执行相关耗时动作。

2.启动另外一个线程B连续向Queue压入元素。

问题现象:

线程B连续压入的元素,弹出的元素值均为最后一次压入的元素值。

问题原因:

网上查找问题原因

1)C#中的Queue类是一个先进先出(FIFO)的数据结构,它使用一个数组来存储队列中的元素。当你向一个空的Queue中添加元素时,它会直接存储在数组的第一个位置上。

当你弹出一个元素后,Queue会将数组中的元素向前移动一个位置,填补被弹出的元素位置。这样,新添加的元素会被放置在队列的末尾。

所以,如果你在没有弹出队列中的所有元素之前再次添加一个元素,那么这个新添加的元素会被放置在队列的末尾。当你继续弹出元素时,它们将按照添加的顺序依次被弹出,而最后一个添加的元素将成为队列中的第一个元素,并且覆盖之前添加的元素。

如果你希望保留之前添加的元素并且不被覆盖,你可以在添加新元素之前先将队列中的所有元素弹出,然后再将它们添加回队列中。或者你可以考虑使用其他数据结构,比如List,根据需要进行操作。

2)网上查找给出一定思路,本身Queue不是线程安全的,那么采用线程安全的队列ConcurrentQueue(),但问题依然存在。

3)继续以ConcurrentQueue进行排查:

C#的ConcurrentQueue是一种线程安全的队列,可以在多线程环境下进行并发操作。当一个线程在另一个线程执行弹出操作期间连续添加元素时,导致新添加的元素覆盖之前已经弹出的值的原因可能是由于在弹出操作期间,另一个线程执行了入队操作,导致队列被修改。

由于ConcurrentQueue是线程安全的,它内部使用了一些同步机制来确保多个线程可以安全地对队列进行操作。但是,即使使用了同步机制,当一个线程在另一个线程执行弹出操作期间连续添加元素时,也可能会发生竞争条件。这种竞争条件会导致新添加的元素覆盖之前已经弹出的值

为了解决这个问题,你可以在添加元素之前先判断队列是否为空,或者使用锁来保护对队列的并发操作。另外,你还可以考虑使用其他数据结构或者调整程序逻辑来避免这种情况的发生。

问题确认:

1)在压入队列前、弹出队列后,均进行变量指向地址的打印,发现地址相同,可以明确,数据被覆盖。

问题解决:

1)采用Lock锁,确保线程B同次的压入和弹出在一次执行完成。即重写ActionTrigger()方法用于线程B的调用,并且删除ThreadPool多线程处理。

http://www.lryc.cn/news/141169.html

相关文章:

  • python3GUI--模仿一些b站网页端组件By:PyQt5(详细介绍、附下载地址)
  • 聚类分析概述
  • 建模杂谈系列234 基于图的程序改造
  • requestAnimationFrame(RAF)
  • 【JavaScript笔记】面对对象与构造函数
  • ​LeetCode解法汇总5-正则表达式匹配​
  • 前端开发工具: VSCode
  • 【Stable-Diffusion-WebUI】Windows系统安装Stable-Diffusion-WebUI
  • 面试题(三)
  • 谈谈子网划分的定义、作用、划分方式以及案例
  • BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(下)
  • Pandas数据分析教程-pandas的数据结构
  • ChatGPT在医疗系统的应用探索动态
  • 【FreeRTOS】【应用篇】任务管理相关函数
  • 第一个react应用程序并添加样式
  • Java——Object类
  • CotEditor for mac 4.0.1 中文版(开源文本编辑器)
  • 【大数据】图解 Hadoop 生态系统及其组件
  • c++ qt--事件过滤(第七部分)
  • Inventor软件安装包分享(附安装教程)
  • STM32F103 4G Cat.1模块EC200S使用
  • 38、springboot为 spring mvc 提供的静态资源管理,覆盖和添加静态资源目录
  • Go 输出函数
  • L1-037 A除以B(Python实现) 测试点全过
  • 睿思BI旗舰版V5.3正式发布
  • 基于Jenkins自动化部署PHP环境---基于rsync部署
  • 学信息系统项目管理师第4版系列02_法律法规
  • 【大数据】Doris:基于 MPP 架构的高性能实时分析型数据库
  • 【rust/egui】(五)看看template的app.rs:SidePanel、CentralPanel以及heading
  • MTK6833_MT6833核心板_天玑700安卓5G核心板规格性能介绍