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

这篇具有很好参考价值的文章主要介绍了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多线程处理。文章来源地址https://www.toymoban.com/news/detail-673054.html

到了这里,关于C#Queue<T>队列出现弹出元素被最后一次压入得元素覆盖的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记一次压测程序时的OOM分析过程

    背 景:在一个项目调优的过程中,丰富了一些组件后,再次对项目进行压测,发现和之前的性能差距甚大,并且每次运行一段时间后,延迟骤增,带宽骤降,查看程序日志,发现了 OutOfMemory:java heap memory ; 现在知道了结果是OOM了,why? 逐步对比程序新增内容,未发现会导致

    2024年01月24日
    浏览(24)
  • 用 Go 剑指 Offer 31. 栈的压入、弹出序列 (辅助栈)

    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。 示例

    2023年04月14日
    浏览(25)
  • 剑指 Offer 31. 栈的压入、弹出序列 / LeetCode 946. 验证栈序列(栈模拟)

    链接:剑指 Offer 31. 栈的压入、弹出序列;LeetCode 946. 验证栈序列 难度:中等 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的 所有数字均不相等 。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序

    2024年02月16日
    浏览(35)
  • 剑指29.顺时针打印矩阵 31 栈的压入,弹出序列 03 数组中的重复数字 53缺失的数字 04二维数组中的查找

    回字形 思路:pushed数组里遍历进栈,遍历时候,先进栈,再判断栈顶是否和poped序列的当前指向的是否一样,一样就pop,直到不一样为止,然后继续遍历进栈。然后再判断栈里面剩余的和poped序列指向的一不一样,一样,就把栈里面的pop,直到栈为空,只要有一个不一样,就

    2024年02月16日
    浏览(31)
  • 【C++】——栈和队列(stack、queue)及优先队列(priority_queue)的介绍和模拟实现

    今天我们来学习C++stl六大组件的其中一种,容器适配器,stack、queue及priority_queue都是容器适配器。我们循序渐进,接下来让我们先认识一下什么是容器适配器。 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该

    2024年02月08日
    浏览(34)
  • 【数据结构】 队列(Queue)与队列的模拟实现

    队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有==先进先出FIFO(FirstIn First Out) ==入队列: 进行插入操作的一端称为 队尾(Tail/Rear) 出队列: 进行删除操作的一端称为 队头(Head/Front) 在Java中, Queue是个接口,底层是通过链表实现

    2024年02月11日
    浏览(37)
  • leetcode分类刷题:队列(Queue)(一、单调队列)

    单调队列,看起来是与单调栈对应起来的一样;但是做题的时候感觉单调队列不像单调栈一样,能根据题意自然形成 单调队列的基本实现 ,感觉单调队列更像是和某个队列对应起来的一样 1、 单调队列的经典题型 :使用双向队列维护窗口,窗口移动的元素增删与队列的先进

    2024年02月09日
    浏览(30)
  • 最后一次模拟考试题解

    哦我想这不用看都知道是为了水任务 其实这题有原 什么手写体 md (指 markdown) 分析 首先这题 如果你题目没看错的话 ,会发现其实他是 n × m n times m n × m 让你求 n × n n times n n × n 的区域内的点(不会只有我一个人题目看错了罢 然后我们会发现其实我们只关心每一列放了多少

    2024年02月14日
    浏览(24)
  • 队列(Queue)的顶级理解

    目录 1.队列(Queue) 的概念 2.单链表模拟实现队列 2.1创建队列 2.2入队列 2.3判断是否为空 2.4出队列 2.5获取队头元素 2.6完整代码: 2.7双向链表模拟实现队列代码 3.数组模拟实现队列代码 3.1创建队列  3.2判断是否为满 3.3检查是否为空   3.4插入元素  3.5删除元素  3.6从队首获取元

    2024年02月09日
    浏览(31)
  • C# 队列(Queue)

    目录 一、概述 二、基本的用法 1.添加元素 2.取出元素 1)Dequeue 方法 2)Peek 方法 3.判断元素是否存在 4.获取队列的长度 5.遍历队列 6.清空容器 7.Queue 泛型类 三、结束 表示对象的先进先出集合。 队列和其他的数据结构一样,是一种存储容器,它遵循 先进先出 的原则,能够存

    2024年02月12日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包