C#各种锁知识点

先上总结: 

锁类型 特点 适用场景 优点 缺点
自旋锁 忙等待实现锁定,适合高并发短时间锁定 高并发环境,短时间锁定,仅限单进程多线程同步 开销低,避免线程上下文切换 忙等待消耗CPU资源,不适合长时间锁定,不能跨进程使用
互斥锁 提供独占访问,阻塞等待,适合长时间锁定 需要跨线程或进程保护资源 阻塞等待不占用CPU资源,支持跨进程 开销高,可能导致死锁,涉及线程上下文切换
Redis分布式锁 基于Redis的分布式锁定,适合分布式系统 分布式环境中的资源协调 适用于分布式系统,提供全局一致性锁 依赖Redis服务,可能受网络延迟影响,需处理锁的过期和续期问题
lock关键字 基于Monitor的代码块级同步机制,易用 简单的线程同步,保护共享资源 语法简单,自动处理异常 需选择合适锁对象,粒度问题,不能跨进程使用,有线程上下文切换的开销

粒度:锁的粒度是指锁定代码块的范围。如果锁定范围太大,会减少并发性,影响性能。 尽量减少锁定代码块的大小,只锁定必要的部分。

 自旋锁(Spin Lock)

  • 特点:当线程尝试获取锁时,如果锁已经被其他线程持有,线程会不停地检查锁是否可用(即“自旋”),直到获取到锁为止。
  • 优点:适用于锁定时间很短的场景,避免了线程的上下文切换,提高了性能。
  • 缺点:如果锁定时间较长,自旋锁会导致CPU资源的浪费,因为线程会一直占用CPU时间进行忙等待。
  • 使用场景:适用于锁定时间极短的代码段,且需要避免线程上下文切换的开销。
using System;
using System.Threading;

class SpinLockExample
{
    private volatile bool locked = false;

    public void Acquire()
    {
        while (true)
        {
            if (!locked)
            {
                locked = true;
                return;
            }
            Thread.SpinWait(1); // 自旋等待
        }
    }

    public void Release()
    {
        locked = false;
    }
}

class Program
{
    static SpinLockExample spinLock = new SpinLockExample();

    static void CriticalSection()
    {
        Console.WriteLine($"{Thread.CurrentThread.Name} trying to acquire lock");
        spinLock.Acquire();
        Console.WriteLine($"{Thread.CurrentThread.Name} acquired lock");
        // Critical section
        Thread.Sleep(1000);
        Console.WriteLine($"{Thread.CurrentThread.Name} releasing lock");
        spinLock.Release();
    }

    static void Main()
    {
        Thread[] threads = new Thread[3];
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(CriticalSection);
            threads[i].Name = $"Thread {i+1}";
            threads[i].Start();
        }

        foreach (Thread thread in threads)
        {
            thread.Join();
        }
    }
}

 

互斥锁 (Mutex)

特点

  • 互斥锁(Mutex)提供对资源的独占访问。线程如果无法获取锁,会被阻塞并放入等待队列。
  • Mutex 可以用于跨线程和跨进程的锁定。
  • 由操作系统管理,能够确保在一个进程中获得锁时,其他进程无法获得同一个锁。

适用场景

  • 需要在多个线程或多个进程之间同步访问共享资源。
  • 需要锁定时间可能较长的操作。
  • 在本地应用程序或服务中使用。

优点

  • 提供跨进程的锁定机制。
  • 阻塞等待,不占用CPU资源。
  • 适合长时间锁定的操作。

缺点

  • 开销较高,涉及线程上下文切换。
  • 可能导致死锁,特别是在嵌套锁定的情况下。
using System;
using System.Threading;

class MutexExample
{
    static Mutex mutex = new Mutex();

    static void CriticalSection()
    {
        Console.WriteLine($"{Thread.CurrentThread.Name} trying to acquire lock");
        mutex.WaitOne();
        try
        {
            Console.WriteLine($"{Thread.CurrentThread.Name} acquired lock");
            // Critical section
            Thread.Sleep(1000);
        }
        finally
        {
            Console.WriteLine($"{Thread.CurrentThread.Name} releasing lock");
            mutex.ReleaseMutex();
        }
    }

    static void Main()
    {
        Thread[] threads = new Thread[3];
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(CriticalSection);
            threads[i].Name = $"Thread {i+1}";
            threads[i].Start();
        }

        foreach (Thread thread in threads)
        {
            thread.Join();
        }
    }
}

Redis分布式锁

特点

  • Redis分布式锁利用Redis的单线程特性,通过设置键值对实现锁定。
  • 支持分布式环境下的锁定机制,多个节点可以通过共享的Redis实例实现同步。
  • 依赖Redis的高性能和高可用性,可以在大规模分布式系统中使用。

适用场景

  • 分布式系统中多个实例需要同步访问共享资源。
  • 跨多个节点的资源协调和管理。
  • 需要全局一致性的锁。

优点

  • 适用于分布式系统,提供全局一致性锁。
  • 高可用性和持久性,适用于大规模分布式环境。
  • 可以与Redis的其他功能(如发布/订阅、缓存)结合使用。

缺点

  • 依赖外部的Redis服务,可能受到网络延迟和服务可用性的影响。
  • 实现复杂,需要处理锁的过期、自动续期等问题。
  • 存在一定的性能开销,尤其是在高延迟网络环境下。
  • using StackExchange.Redis;
    using System;
    using System.Threading;
    
    class RedisLockExample
    {
        private static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
        private static IDatabase db = redis.GetDatabase();
        private const string LockKey = "lockKey";
    
        public static bool AcquireLock(string lockKey, TimeSpan expiry)
        {
            return db.StringSet(lockKey, "locked", expiry, When.NotExists);
        }
    
        public static void ReleaseLock(string lockKey)
        {
            db.KeyDelete(lockKey);
        }
    
        static void CriticalSection()
        {
            while (!AcquireLock(LockKey, TimeSpan.FromSeconds(5)))
            {
                Thread.Sleep(100); // wait and retry
            }
            try
            {
                Console.WriteLine($"{Thread.CurrentThread.Name} acquired lock");
                // Critical section
                Thread.Sleep(1000);
            }
            finally
            {
                Console.WriteLine($"{Thread.CurrentThread.Name} releasing lock");
                ReleaseLock(LockKey);
            }
        }
    
        static void Main()
        {
            Thread[] threads = new Thread[3];
            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(CriticalSection);
                threads[i].Name = $"Thread {i + 1}";
                threads[i].Start();
            }
    
            foreach (Thread thread in threads)
            {
                thread.Join();
            }
        }
    }
    

 lock关键字

特点

  • lock 关键字基于 Monitor 实现,线程如果无法获取锁,会被阻塞并放入等待队列。
  • 适用于大多数普通的多线程同步场景,锁定时间可以较长。
  • 自动处理异常情况,确保在异常发生时释放锁。

优点

  • 使用方便,语法简洁。
  • 在等待锁时,线程不会消耗CPU资源。
  • 自动处理异常,确保锁的释放。

缺点

  • 有线程上下文切换的开销。
  • 需要选择合适的锁对象,避免锁定 this 或公共对象。
  • 不能跨进程使用。
class LockExample
{
    private readonly object lockObj = new object();

    public void CriticalSection()
    {
        lock (lockObj)
        {
            // Critical section
        }
    }
}

相关推荐

  1. C#各种知识

    2024-07-21 23:50:04       27 阅读
  2. 知识总结,cc++的各种知识

    2024-07-21 23:50:04       38 阅读
  3. mysql 知识简述

    2024-07-21 23:50:04       46 阅读
  4. C++】知识汇总(下)

    2024-07-21 23:50:04       47 阅读
  5. C++】知识汇总(上)

    2024-07-21 23:50:04       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 23:50:04       106 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 23:50:04       116 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 23:50:04       95 阅读
  4. Python语言-面向对象

    2024-07-21 23:50:04       103 阅读

热门阅读

  1. Python之后端Django(四)

    2024-07-21 23:50:04       27 阅读
  2. n4.Nginx 核心模块

    2024-07-21 23:50:04       25 阅读
  3. android audio 相机按键音:(二)加载与修改

    2024-07-21 23:50:04       29 阅读
  4. 数字转换(树形DP)

    2024-07-21 23:50:04       26 阅读
  5. python 爬虫技术 第03节 基础复习 控制结构

    2024-07-21 23:50:04       23 阅读
  6. Python 模块导入方式

    2024-07-21 23:50:04       26 阅读
  7. 基于最新版的flutter pointycastle: ^3.9.1的AES加密

    2024-07-21 23:50:04       24 阅读
  8. Shiro-550反序列化漏洞

    2024-07-21 23:50:04       19 阅读
  9. Kotlin单例、数据类、静态

    2024-07-21 23:50:04       29 阅读