C#Queue

C#队列的线程安全问题
在上一篇博客https://zhuanlan.zhihu.com/p/412083493里提到了用队列这种数据结构来存储串口数据的方法,看评论里有提到我的队列没有加锁,线程不安全,仔细研究了下,确实不安全,这里感谢大佬提醒。

队列是其元素以**先进先出(FIFO)**的方式来处理集合,先入队的元素会先读取。

队列在现实生活中的例子数不胜数。例如:排队打饭,排队购买机票,打印队列中等待处理的打印业务等

解决方法:
使用ConcurrentQueue类来代替Queue类。

测试代码:

这里分别定义了一个ConcurrentQueue类和Queue类来进行测试。

一个线程Enqueue 10000个数据的,另一个Dequeue 5000个数,如果线程安全,最后应该还有5000个数

代码如下:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StackQueue
{
    class Program
    {
        public static Queue<Product> productQueue = new Queue<Product>(50000);//定义一个队列-----存在并发风险
 
        public static ConcurrentQueue<Product> productCQ = new ConcurrentQueue<Product>();//无需考虑并发

        static void Main(string[] args)
        {
            //普通入队操作  存在并发风险
            Task t1 = new TaskFactory().StartNew(RuDui);
            //普通出队操作  存在并发风险
            Task t2 = new Task(() => ChuDui());
            t2.Start();
            Task.WaitAll(t1, t2);
            Console.WriteLine("productQueue队列中共有元素:" + productQueue.Count + "个。实际应该有5000个");

            //安全入队操作  存在并发风险
            Task t3 = new TaskFactory().StartNew(RuDuiCC);
            //安全出队操作  存在并发风险
            Task t4 = new Task(() => ChuDuiCC());
            t4.Start();
            Task.WaitAll(t3, t4);
            Console.WriteLine("productCQ队列中共有元素:" + productCQ.Count + "个。实际应该有5000个");

            Console.ReadKey();
        }

        public static void RuDui() //定义一个入队方法  先进先出(不安全)
        {
            for (int i = 1; i < 10001; i++)
            {
                Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = 10 };
                productQueue.Enqueue(model);
            }
        }
        public static void ChuDui()//定义一个出队方法  先进先出(不安全)
        {
            
            for (int i = 1; i < 5001; i++)
            {
                while (productQueue.Count < 1) ;
                productQueue.Dequeue();
            }
        }



        public static void RuDuiCC() //保证线程安全的入队方法
        {
            for (int i = 1; i < 10001; i++)
            {
                Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = 10 };
                productCQ.Enqueue(model);
            }
        }
        public static void ChuDuiCC() //保证线程安全的出队方法
        {
            Product re;
            for (int i = 1; i < 5001; i++)
            {
                while (productCQ.Count < 1) ;
                productCQ.TryDequeue(out re);
            }
        }


    }


    public class Product
    {
        public string Name { get; set; }
        public string Category { get; set; }
        public int SellPrice { get; set; }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值