「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。
欢迎各位朋友微信搜索「Andy阿辉」关注一波!
写一些程序员的所思所想,希望对你有帮助。
前言
大家好,我是阿辉。
前面了解了ConcurrentDictionary和ConcurrentQueue,今天来看看ConcurrentStack,它是线程安全的堆栈集合,是一种后进先出的对象集合。当需要对各项业务进行后进先出访问时,则使用堆栈。
推入元素:列表中添加一项。弹出元素:从列表中移除一项。
一般的堆栈集合是线程不安全的,也就是说当有多个线程同时访问的时候,值可能会被多个线程抢着取值和赋值,可能在操作的过程中出现数据丢失的问题。一般的情况是加锁,它能保证在同一时刻,某个变量只能被一个线程独占,其余的线程只能进行等待,待其使用完毕后才能进行使用。但锁的引入会带来一定的开销和性能的损耗,并降低程序的扩展性,有时候可能会出现死锁的可能。
死锁: 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵局状态时,若无外力作用,它们都将无法在向前推进。
堆栈对应的线程安全的并发集合是ConcurrentStack。
Push(): 从顶部插入一个元素。
TryPop(): 移除并返回集合顶部的元素。
TryPeek: 返回顶部的元素,但是不从集合中删除。
Demo
class Program
{
static int num = 0;
private static ConcurrentStack<int> stack = new ConcurrentStack<int>(); //线程安全的队列
static void Main(string[] args)
{
Thread oneThread = new Thread(new ThreadStart(Push));
oneThread.Start();
Thread.Sleep(10);
for (int i = 0; i < 10; i++)
{
var value = num + i;
Console.WriteLine("主线程入栈"+value);
stack.Push(value);
}
oneThread.Abort();
//输出堆栈中的数据
int count = stack.Count;
int result;
for (int i = 0; i < count; i++)
{
if (stack.TryPop(out result))
{
Console.WriteLine("出栈:"+result);
}
}
Console.ReadKey();
}
static void Push()
{
while (true)
{
num += 5;
//Thread.Sleep(0);
Console.WriteLine("one线程入栈" + num);
stack.Push(num);
}
}
}
在实际的业务中,应该根据实际的业务场景,看是选择线程不安全的集合还是选择线程安全,内部使用原子操作的堆栈对象集合来实现。
小寄语
人生短暂,我不想去追求自己看不见的,我只想抓住我能看得见的。
原创不易,给个关注。
我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发 谢谢。