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

栈是和队列非常类似的另一个容器,栈和队列最大的区别是后进先出(LIFO),也可以说成先进后出。

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

栈在生活中的例子也不少。例如:物流装车,火车调度等

那么,关于队列和栈在C#的用法介绍如下:

队列主要用法:

栈主要用法:

上述两个图中分别展示了队列:Queue<T>及栈Stack<T>

而在实际的C#编程中,无论是Queue<T>还是Stack<T>都无法保证线程安全,换句话说,他们存在普通集合List<T>存在的并发问题。关于这个问题,大家可以参考我的博客:C# 集合-并发处理-锁OR线程

今天,我写简单写了一个案例,分享给大家,代码如下:

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>();//定义一个队列-----存在并发风险
public static Stack<Product> productStack = new Stack<Product>();//定义一个栈-----存在并发风险
//Net 4.0以后,微软提供了线程安全的先进先出集合
public static ConcurrentQueue<Product> productCQ = new ConcurrentQueue<Product>();//无需考虑并发
//Net 4.0以后,微软提供了线程安全的先进后出集合
public static ConcurrentStack<Product> productSK = new ConcurrentStack<Product>();//无需考虑并发
static void Main(string[] args)
{
//普通入队操作 存在并发风险
Task t1 = new TaskFactory().StartNew(RuDui);
Task t2 = new Task(()=>RuDui());
t2.Start();
Task t3 = Task.Factory.StartNew(RuDui);
Task t4 = Task.Run(() => RuDui());
Task.WaitAll(t1, t2, t3, t4);
//
//
//普通入栈操作,存在并发风险
Task t5 = new TaskFactory().StartNew(RuZhan);
Task t6 = new Task(() => RuZhan());
t6.Start();
Task t7 = Task.Factory.StartNew(RuZhan);
Task t8 = Task.Run(() => RuZhan());
Task.WaitAll(t5, t6, t7, t8);
//
//
//线程安全的入队操作,无需考虑并发问题<微软底层帮你处理了 ~_~ >
Task t11 = new TaskFactory().StartNew(RuDuiCC);
Task t22 = new Task(() => RuDuiCC());
t22.Start();
Task t33 = Task.Factory.StartNew(RuDuiCC);
Task t44 = Task.Run(() => RuDuiCC());
Task.WaitAll(t11, t22, t33, t44);
//
//
//线程安全的入栈操作,无需考虑并发问题<微软底层帮你处理了 ~_~ >
Task t55 = new TaskFactory().StartNew(RuZhanCC);
Task t66 = new Task(() => RuZhanCC());
t66.Start();
Task t77 = Task.Factory.StartNew(RuZhanCC);
Task t88 = Task.Run(() => RuZhanCC());
Task.WaitAll(t55, t66, t77, t88);
//
//
Console.WriteLine("productQueue队列中共有元素:" + productQueue.Count + "个。实际应该有40000个元素。存在并发风险!");
Console.WriteLine("productStack栈中共有元素:" + productStack.Count + "个。实际应该有40000个元素。存在并发风险!");
Console.WriteLine("productCQ队列中共有元素:" + productCQ.Count + "个。实际应该有40000个元素。无需考虑并发风险!");
Console.WriteLine("productSK栈中共有元素:" + productSK.Count + "个。实际应该有40000个元素。无需考虑并发风险!");
Console.ReadKey();
} public static void RuDui() //定义一个入队方法 先进先出
{
for (int i = ; i < ; i++)
{
Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = };
productQueue.Enqueue(model);
}
} public static void RuZhan() //定义一个入栈方法 先进后出
{
for (int i = ; i < ; i++)
{
Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = };
productStack.Push(model);
}
} public static void RuDuiCC() //保证线程安全的入队方法
{
for (int i = ; i < ; i++)
{
Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = };
productCQ.Enqueue(model);
}
} public static void RuZhanCC() //保证线程安全的入栈方法
{
for (int i = ; i < ; i++)
{
Product model = new Product() { Name = "商品" + i, Category = "水果", SellPrice = };
productSK.Push(model);
}
}
} public class Product
{
public string Name { get; set; }
public string Category { get; set; }
public int SellPrice { get; set; }
}
}

执行结果如下:

由此可见,Queue<T>入队和Stack<T>入栈都存在并发的问题。

上述代码中,提供了ConcurrentQueue<T> 和 ConcurrentStack<T> 两种全新的队列、栈。代码注释中也提到,这是NETFRM4.0才提出的线程安全队列及栈集合。

换句话说,使用ConcurrentQueue<T> 和 ConcurrentStack<T> 两种全新的队列、栈,无需考虑并发问题!

当然,如果您不习惯使用ConcurrentQueue<T> 和 ConcurrentStack<T> ,那么您也可以结合C# Lock(Object) 进行代码临界,这种加锁的方式也能解决Queue<T>和Stack<T>并发的问题。不过,加锁就意味着额外开销,效率会低一些。

加锁的方式在我的博客:C# 集合-并发处理-锁OR线程 中都有体现。

更多兴趣阅读<也是关于队列应用的哦>:C# 定时器和队列结合,卖包子啦,Timer、 AutoResetEvent、 ManualResetEvent

当然,如果遍历队列或者栈,可以使用Foreach(var A in ...)

今天只是做个整理,没什么特别的意义,有兴趣的小虎斑点个赞吧!谢谢!

@陈卧龙的博客

C# 队列和栈 线程安全的更多相关文章

  1. python的队列和栈

    (一)队列和栈的区别 1.队列: 队列是一种特殊的线性表.其两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进),允许删除的一端称为队尾(rear),允许插入的一端 ...

  2. Callable、Future&阻塞队列&阻塞栈

    Callable.Future   简单应用 在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了.现在Java终于有可返回值的任务( ...

  3. 数据结构之队列and栈总结分析

    一.前言: 数据结构中队列和栈也是常见的两个数据结构,队列和栈在实际使用场景上也是相辅相成的,下面简单总结一下,如有不对之处,多多指点交流,谢谢. 二.队列简介 队列顾名思义就是排队的意思,根据我们的 ...

  4. python优先队列,队列和栈

    打印列表的疑问 class Node: def __str__(self): return "haha" print([Node(),Node()]) print(Node()) ...

  5. JavaScript数据结构,队列和栈

    在JavaScript中为数组封装了大量的方法,比如:concat,pop,push,unshift,shift,forEach等,下面我将使用JavaScript提供的这些方法,实现队列和栈的操作. ...

  6. C语言算法系列---1.队列和栈

    写在前面:在家玩了好久,实在是不知道干嘛了,突然想找些事做,现在是时候做些什么了.这些东西不见得多高深,也可能很简单,但很基础,也无法忽视.同时,也是自己学习走过的一条路. 这是开头,就写写C的队列和 ...

  7. POJ 1879 Tempus et mobilius Time and motion 队列和栈

    很简单的队列和栈的应用,不过读明白题意非常重要:(直接引用白书的题解)三个轨道,一个库.分别是分钟单位的轨道,5min单位的轨道,一小时单位的轨道,还有就是n容量的库.每过一分钟,一个小球从库里面出来 ...

  8. 【三支火把】---队列和栈的C程序实现

    这几天总结了C语言的队列,栈的实现方法,在此总结一下:一.栈 首先从栈开始,诚然,相信学习过数据结构的你,肯定应该知道栈是什么东西了,如果不知道也没事每一句话我就可以帮你总结--数据只在栈顶进行插入和 ...

  9. 225 Implement Stack using Queues(用队列实现栈Medium)

    题目意思:用队列实现栈,push(),pop(),top(),empty() 思路:用两个queue,pop时将一个queue的元素pop再push到另一个队列,queue只留最后一个元素,并pop, ...

随机推荐

  1. Android学习笔记----ArcGIS在线地图服务(Android API)坐标纠偏

    仅限于如下ArcGIS在线地图服务(高德提供数据): //概述:彩色中文含兴趣点版中国基础地图 //投影:WGS 1984 Web-Mercator //切片格式:MIXED90 //服务类型:基础地 ...

  2. Jenkins 开启用户注册机制及用户权限设置

    Jenkins 开启用户注册机制及用户权限设置   by:授客 QQ:1033553122 步骤 1.  系统管理-Configure Global Security 2.  设置

  3. 安卓开发_浅谈Action Bar

    一.Action Bar 导航栏.是3.0之后出现的. 所以注意使用的时候清单文件要设置下 android:minSdkVersion="11"(至少11) 但如果使用v4包,则不 ...

  4. linux(乌班图)修改apt下载源

    有时候会出现乌班图系统刚安装,无法使用apt下载安装软件工具,此时需要修改apt下载源. 1.进入/etc/apt/目录下  2.备份sources.list文件(如果不在root用户下,需在前面加s ...

  5. selenium元素定位(Java)

    1.使用findElement方法定位元素   findElement()方法:当开始寻找符合指定条件的元素时,它将查询整个DOM,然后返回第一个找到的匹配元素.   By id:通过元素ID属性定位 ...

  6. (网页)js每隔5分钟执行一次ajax请求的实现方法(转)

    转自脚本之家: 一个页面好像只能有一个 window.onload=function(){},所以要有多个事件,这样写就好了 window.onload=function(){ //假设这里每个五分钟 ...

  7. (后台)java 读取excel 文件 Unable to recognize OLE stream 错误

    原因:不支出读取 excel 2007 文件(*.xlsx).只支持 excel 2003 (*.xls). 光修改文件后缀不行,需要文件另存(或者导出)为 .xls Excel 1997-2004 ...

  8. 对JavaScript中闭包的理解

    在前端开发中闭包是一个很重要的知识点,是面试中一定会被问到的内容.之前我对闭包的理解主要是"通过闭包可以在函数外部能访问到函数内部的变量",对闭包运用的也很少,甚至自己写过闭包自己 ...

  9. 简单易懂的程序语言入门小册子(1):基于文本替换的解释器,lambda演算

    最近比较闲,打算整理一下之前学习的关于程序语言的知识.主要的内容其实就是一边设计程序语言一边写解释器实现它.这些知识基本上来自Programming Languages and Lambda Calc ...

  10. Python+Pandas 读取Oracle数据库

    Python+Pandas 读取Oracle数据库 import pandas as pd from sqlalchemy import create_engine import cx_Oracle ...