c#中使用lock创建一个简单的队列示例

一.背景

在我威某人的浅薄理解下,队列主要解决的问题,确保某些场景可以按顺寻处理避免混乱和延误并且可以按优先级入队处理,比较常见的场景有以下这五点:

1.订单处理和物流管理

2.客户服务和支持

3.数据处理和分析

4.任务调度和执行

5.消息传递和通信

二.实现:

1.首先我们创建一个简单的队列帮助类如下图

 

2.帮助类中的代码

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace ConsoleApp1.Models
 8 {
 9     public class SimpleQueue<T>
10     {
11         private readonly Queue<T> _queue = new Queue<T>();
12         private readonly object _lock = new object();  // 锁对象
13 
14         // 入队操作
15         public void Enqueue(T item)
16         {
17             lock (_lock)  // 确保线程安全
18             {
19                 _queue.Enqueue(item);
20                 Console.WriteLine($"Item enqueued: {item}");
21             }
22         }
23 
24         // 出队操作
25         public T Dequeue()
26         {
27             lock (_lock)  // 确保线程安全
28             {
29                 if (_queue.Count == 0)
30                 {
31                     throw new InvalidOperationException("Queue is empty");
32                 }
33 
34                 T item = _queue.Dequeue();
35                 Console.WriteLine($"Item dequeued: {item}");
36                 return item;
37             }
38         }
39 
40         // 查看队列是否为空
41         public bool IsEmpty()
42         {
43             lock (_lock)
44             {
45                 return _queue.Count == 0;
46             }
47         }
48     }
49 }

如何调用:

如下是在Program中调用代码,代码细节请查看注释

 1 // See https://aka.ms/new-console-template for more information
 2 using ConsoleApp1.Models;
 3 
 4 Console.WriteLine("Hello, World!");
 5 var queue = new SimpleQueue<int>();
 6 
 7 // 创建生产者线程
 8 Thread producer = new Thread(() =>
 9 {
10     for (int i = 0; i < 10; i++)
11     {
12         queue.Enqueue(i);
13         Thread.Sleep(100);  // 模拟一些延迟
14     }
15 });
16 
17 // 创建消费者线程
18 Thread consumer = new Thread(() =>
19 {
20     for (int i = 0; i < 10; i++)
21     {
22         if (!queue.IsEmpty())
23         {
24             queue.Dequeue();
25         }
26         Thread.Sleep(150);  // 模拟一些延迟
27     }
28 });
29 
30 producer.Start();
31 consumer.Start();
32 
33 producer.Join();
34 consumer.Join();
35 
36 Console.WriteLine("Queue processing completed.");

运行结果如下图:

代码说明:

  • 队列的基本操作

    • Enqueue(T item):将元素添加到队列尾部。
    • Dequeue():从队列头部移除并返回一个元素。
    • IsEmpty():检查队列是否为空。
  • 线程安全

    • 使用了 lock 关键字,它将某一代码块包裹起来,使同一时间只能有一个线程进入该代码块,其他线程会被阻塞,直到当前线程释放锁。
    • 锁定的是 _lock 对象,这个对象在整个队列生命周期中保持唯一,确保对队列的每次操作(入队、出队等)是互斥的

 总结:

好的终于到了大家伙最不舍的总结环节,那让我来总结一下吧!!!

  • 优点

    • 简单明了,使用 lock 可以确保对共享资源的访问是安全的,不会产生并发问题。
    • 适合简单的队列需求,代码易于理解和维护。
  • 缺点

    • 锁的使用会导致线程阻塞,尤其在高并发环境下,大量的线程可能因为竞争锁而等待,降低了性能。
    • 锁的使用并不高效,特别是在大量入队、出队操作时,可能会带来不必要的开销。

 虽然使用锁可以实现线程安全的队列,但在高并发场景下,锁的开销可能比较高。如果需要高并发性能可以考虑使用无锁队列如 .NET 中的 ConcurrentQueue<T>)或其他更复杂的并发控制机制来优化性能。

posted @ 2024-09-18 10:42  echo_sw  阅读(27)  评论(0编辑  收藏  举报