Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Thuộc tính Array.SyncRoot trong C# - Đồng bộ hóa mảng

Thuộc tính Array.SyncRoot trả về một đối tượng dùng để khóa (lock) khi truy cập mảng từ nhiều luồng (thread), đảm bảo an toàn luồng (thread safety) cho các thao tác liệt kê (enumeration) hoặc sửa đổi mảng.

Tại sao cần SyncRoot?

  • Mảng trong C# không an toàn luồng (not thread-safe) cho việc ghi/đọc đồng thời.
  • Duyệt mảng (foreach) trong khi luồng khác sửa đổi mảng → ném InvalidOperationException.
  • SyncRoot cung cấp đối tượng khóa chuẩn cho mảng, dùng với lock.

Ví dụ: Khóa mảng khi duyệt

using System;
using System.Threading;

class Program
{
    static int[] sharedArray = { 23, 11, 32, 18, 87 };
    
    static void Main()
    {
        // Luồng 1: Duyệt mảng
        Thread t1 = new Thread(() =>
        {
            lock (sharedArray.SyncRoot)
            {
                foreach (object val in sharedArray)
                {
                    Console.WriteLine($"Reader: {val}");
                    Thread.Sleep(50); // Giả lập xử lý
                }
            }
        });
        
        // Luồng 2: Sửa đổi mảng (cần lock cùng đối tượng)
        Thread t2 = new Thread(() =>
        {
            lock (sharedArray.SyncRoot)
            {
                Thread.Sleep(100); // Đợi reader vào trước
                sharedArray[0] = 999;
                Console.WriteLine("Writer: Đã thay đổi phần tử đầu tiên");
            }
        });
        
        t1.Start(); t2.Start();
        t1.Join(); t2.Join();
    }
}

Lưu ý quan trọng

  • lock(arr.SyncRoot) chỉ bảo vệ nếu tất cả luồng đều lock trên cùng đối tượng SyncRoot trước khi truy cập mảng.
  • Mảng 1 chiều (vector) có SyncRoot trả về chính mảng đó (this). Mảng đa chiều trả về đối tượng wrapper.
  • Từ .NET 2.0+, khuyến nghị dùng Generic Collections (List<T>, ConcurrentBag<T>...) thay vì mảng raw cho đa luồng.
  • Đối với List<T>, dùng lock(((ICollection)list).SyncRoot) hoặc tốt hơn: dùng ImmutableList<T> hoặc ConcurrentBag<T>.

So sánh

Cách làmƯu điểmNhược điểm
lock(arr.SyncRoot)Đơn giản, built-inCoarse-grained lock, dễ deadlock nếu lồng nhau
Concurrent CollectionsLock-free, hiệu năng caoAPI phức tạp hơn
Immutable CollectionsThread-safe by designTạo bản copy khi sửa đổi