C#多线程开发-并发集合中的ConcurrentStack

309 阅读2分钟

「这是我参与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);   
            }            
        }
    }

在实际的业务中,应该根据实际的业务场景,看是选择线程不安全的集合还是选择线程安全,内部使用原子操作的堆栈对象集合来实现。

小寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看得见的。

原创不易,给个关注。

我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发 谢谢。