Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

เมธอด Queue.Synchronized() ใน C# : สร้างคิวที่ Thread-Safe

เมธอด Queue.Synchronized() ใน C# ใช้สร้าง Wrapper ใหม่ที่ห่อหุ้ม Queue ต้นฉบับ ทำให้เป็น Thread-Safe (ปลอดภัยต่อการเข้าถึงจากหลายเธรดพร้อมกัน) คืนค่า Queue ใหม่ที่ synchronized

รูปแบบไวยากรณ์ (Syntax)

public static Queue Synchronized(Queue queue);
  • queue : Queue ต้นฉบับที่ต้องการทำให้ thread-safe
  • คืนค่า : Queue ใหม่ที่ synchronized (wrapper)

ตัวอย่างที่ 1: ตรวจสอบ IsSynchronized

using System;
using System.Collections;

public class Demo
{
    public static void Main()
    {
        Queue queue = new Queue();
        
        queue.Enqueue("AB");
        queue.Enqueue("BC");
        queue.Enqueue("CD");
        queue.Enqueue("DE");
        queue.Enqueue("EF");
        queue.Enqueue("FG");
        queue.Enqueue("GH");
        queue.Enqueue("HI");
        
        Console.WriteLine("Queue...");
        IEnumerator demoEnum = queue.GetEnumerator();
        while (demoEnum.MoveNext())
        {
            Console.WriteLine(demoEnum.Current);
        }
        
        Console.WriteLine("Is Queue synchronized? = " + queue.IsSynchronized); // False
        
        Queue queue2 = Queue.Synchronized(queue);
        
        Console.WriteLine("Is Queue synchronized now? = " + queue2.IsSynchronized); // True
    }
}

ผลลัพธ์

Queue...
AB
BC
CD
DE
EF
FG
GH
HI
Is Queue synchronized? = False
Is Queue synchronized now? = True

ตัวอย่างที่ 2: ใช้งาน Synchronized Queue

using System;
using System.Collections;

public class Demo
{
    public static void Main()
    {
        Queue queue = new Queue();
        
        queue.Enqueue(100);
        queue.Enqueue(200);
        queue.Enqueue(300);
        
        Console.WriteLine("Is Queue synchronized? = " + queue.IsSynchronized); // False
        
        Queue queue2 = Queue.Synchronized(queue);
        
        Console.WriteLine("Is Queue synchronized now? = " + queue2.IsSynchronized); // True
        Console.Write("Count of elements = ");
        Console.WriteLine(queue.Count);
        
        Console.WriteLine("Queue...");
        foreach (int i in queue)
        {
            Console.WriteLine(i);
        }
        
        Console.WriteLine("Does the queue have element 500? = " + queue.Contains(500));
        
        // CopyTo ทดสอบกับ synchronized queue
        int[] intArr = new int[5];
        intArr[0] = 1;
        intArr[1] = 2;
        intArr[2] = 3;
        intArr[3] = 4;
        intArr[4] = 0;
        
        queue.CopyTo(intArr, 1); // คัดลอกจาก queue ไป array เริ่ม index 1
        
        Console.WriteLine("\nQueue (unchanged)");
        foreach (int i in queue)
        {
            Console.WriteLine(i);
        }
        
        Console.WriteLine("\nArray (updated)");
        foreach (int i in intArr)
        {
            Console.WriteLine(i);
        }
    }
}

ผลลัพธ์

Is Queue synchronized? = False
Is Queue synchronized now? = True
Count of elements = 3
Queue...
100
200
300
Does the queue have element 500? = False
Queue (unchanged)
100
200
300
Array (updated)
1
100
200
300
0

สรุปและข้อควรระวัง

  • เฉพาะ Non-generic Queue (System.Collections.Queue) เท่านั้นที่มี Synchronized()
  • Queue<T> (Generic) ไม่มี Synchronized() method
  • Wrapper ใช้ lock ภายในทุก operation (Enqueue, Dequeue, Peek, Count, ฯลฯ)
  • ประสิทธิภาพช้ากว่า Queue ธรรมดา เนื่องจาก locking overhead
  • ใน .NET สิ้นใหม่ แนะนำใช้ ConcurrentQueue<T> (System.Collections.Concurrent) แทน ซึ่ง lock-free และประสิทธิภาพดีกว่า
  • Enumeration (foreach) บน Synchronized Queue ไม่ได้ thread-safe ต้อง lock เอง

ตัวเลือกสมัยใหม่: ConcurrentQueue<T>

using System.Collections.Concurrent;

var concurrentQueue = new ConcurrentQueue();
concurrentQueue.Enqueue(1); // Thread-safe โดยไม่ต้อง lock
concurrentQueue.TryDequeue(out int result); // Non-blocking