.NET高级面试指南专题六【线程安全】5种方法解决线程安全问题

.NET高级面试指南专题六【线程安全】5种方法解决线程安全问题_第1张图片

前言

多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题。所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的。
线程安全问题都是由全局变量及静态变量引起的。

线程安全是指在多线程环境中,对共享资源的访问不会导致数据不一致或不确定的结果。在C#中,确保线程安全是至关重要的,因为多个线程并发地访问共享的数据结构可能导致竞态条件(race condition)和数据污染。

.NET中5种方法解决线程安全问题
1.互斥锁(Mutex):
通过lock语句或Mutex类,确保在同一时间只有一个线程能够访问共享资源。

private static object lockObject = new object();
private static int sharedData = 0;

public void IncrementData()
{
    lock (lockObject)
    {
        sharedData++;
    }
}

2.Monitor:
使用Monitor类可以实现类似lock的互斥锁机制。

private static object lockObject = new object();
private static int sharedData = 0;

public void IncrementData()
{
    Monitor.Enter(lockObject);
    try
    {
        sharedData++;
    }
    finally
    {
        Monitor.Exit(lockObject);
    }
}

3.互斥量(Mutex):
使用Mutex类进行跨进程的线程同步。

private static Mutex mutex = new Mutex();
private static int sharedData = 0;

public void IncrementData()
{
    mutex.WaitOne();
    try
    {
        sharedData++;
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}

4.Interlocked 类:
提供原子操作,可以在不使用锁的情况下确保对共享资源的安全访问。

private static int sharedData = 0;

public void IncrementData()
{
    Interlocked.Increment(ref sharedData);
}

5.ReaderWriterLockSlim:
适用于读多写少的场景,提供更细粒度的控制。

private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
private static int sharedData = 0;

public void IncrementData()
{
    rwLock.EnterWriteLock();
    try
    {
        sharedData++;
    }
    finally
    {
        rwLock.ExitWriteLock();
    }
}

示例说明:
考虑一个简单的银行账户类,多个线程可能同时尝试对账户进行存款。为确保线程安全,可以使用lock:

public class BankAccount
{
    private object lockObject = new object();
    private decimal balance = 0;

    public void Deposit(decimal amount)
    {
        lock (lockObject)
        {
            balance += amount;
            Console.WriteLine($"Deposit: {amount}, Balance: {balance}");
        }
    }
}

class Program
{
    static void Main()
    {
        BankAccount account = new BankAccount();

        // 启动多个线程进行并发存款
        Task.Run(() => account.Deposit(100));
        Task.Run(() => account.Deposit(150));

        Console.ReadLine();
    }
}

你可能感兴趣的:(.NET高级面试指南,.net,面试,安全)