首页 > 编程语言 >c# 多线程环境下对共享资源访问的办法

c# 多线程环境下对共享资源访问的办法

时间:2024-08-13 22:15:44浏览次数:12  
标签:Console c# lock void counter 共享资源 static new 多线程

Monitor:

    • 定义:Monitor 是 C# 中最基本的同步机制,通过 Enter 和 Exit 方法来控制对共享资源的访问。它提供了排他锁的功能,确保在任何时刻只有一个线程可以访问共享资源。
    • 优点:简单易用,适合对临界区进行粗粒度的同步控制。
    • 缺点:只能实现排它锁,不能实现读写锁,性能相对较低。

  

class Program
{
    static readonly object _lock = new object();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        Monitor.Enter(_lock);
        try
        {
            _counter++;
            Console.WriteLine($"Counter: {_counter}");
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }
}
Monitor

 

Mutex:

    • 定义:Mutex 是一个操作系统对象,用于在进程间共享,通过 WaitOne 和 ReleaseMutex 来控制对共享资源的访问。它提供了进程间的同步能力。
    • 优点:可跨进程使用,适合在进程间进行同步。
    • 缺点:相比 Monitor,性能开销较大,因为涉及到系统调用。

  

class Program
{
    static Mutex _mutex = new Mutex();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _mutex.WaitOne();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _mutex.ReleaseMutex();
    }
}
Mutex

 

ReaderWriterLockSlim:

    • 定义:ReaderWriterLockSlim 实现了读写分离锁,允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。这种机制适用于读多写少的场景。
    • 优点:适合读多写少的场景,提高了并发性能。
    • 缺点:相对复杂,可能会引起死锁,不支持递归锁。

  

class Program
{
    static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(ReadCounter).Start();
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void ReadCounter()
    {
        _rwLock.EnterReadLock();
        Console.WriteLine($"Counter: {_counter}");
        _rwLock.ExitReadLock();
    }

    static void IncrementCounter()
    {
        _rwLock.EnterWriteLock();
        _counter++;
        Console.WriteLine($"Counter incremented to: {_counter}");
        _rwLock.ExitWriteLock();
    }
}
ReaderWriterLockSlim

 

Semaphore:

    • 定义:Semaphore 是一个信号量,用于控制同时访问共享资源的线程数量。通过 WaitOne 和 Release 方法,可以控制访问资源的线程数量。
    • 优点:可以控制多个线程同时访问共享资源的数量,灵活性较高。
    • 缺点:相对于其他机制,使用起来较为复杂,需要谨慎处理信号量的释放。

  

class Program
{
    static Semaphore _semaphore = new Semaphore(2, 2); // Allow 2 threads to access the resource simultaneously
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _semaphore.WaitOne();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _semaphore.Release();
    }
}
Semaphore

 

SemaphoreSlim:

    • 定义:SemaphoreSlim 是轻量级的信号量,与 Semaphore 类似,用于控制同时访问共享资源的线程数量,但相比 Semaphore 更轻量级。
    • 优点:相比 SemaphoreSemaphoreSlim 的开销更小,适用于资源访问频繁的场景。
    • 缺点:与 Semaphore 相比,功能上略有限制,例如没有 Release(Int32) 方法,只能递增信号量一个单位。
class Program
{
    static SemaphoreSlim _semaphore = new SemaphoreSlim(2, 2); // Allow 2 threads to access the resource simultaneously
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _semaphore.Wait();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _semaphore.Release();
    }
}
SemaphoreSlim

 

lock:

    • 定义:

      lock 关键字用于在代码块级别实现互斥锁,确保共享资源在多线程环境中被安全访问。lock 关键字确保在同一时间只有一个线程可以访问共享资源,从而避免竞态条件和数据损坏。

      此外,lock 关键字在 C# 中是基于 Monitor 的概念实现的。lock 关键字在 C# 中是基于 Monitor 的概念实现的语法糖。当使用 lock 关键字时,它会自动获取对象的监视器锁(Monitor),并在代码块执行完毕后释放这个锁,以确保线程安全性。

    • 优点:
      1. 简单易用:lock 提供了一种简单的方式来实现线程同步,避免了开发人员手动管理锁的复杂性。
      2. 自动释放:lock 会自动释放锁,避免了忘记释放锁导致死锁的情况。
      3. 确保线程安全:通过使用 lock,可以确保共享资源在多线程环境下的安全访问。
    • 缺点:
      1. 潜在死锁:如果在锁内部发生了阻塞操作,可能会导致死锁情况的发生。
      2. 性能开销:频繁使用 lock 可能会导致性能开销,因为其他线程需要等待锁的释放。
      3. 可能引发竞态条件:如果 lock 的粒度过大,可能会导致竞态条件的发生,影响程序性能。
class Program
{
    static readonly object _lock = new object();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        lock (_lock)
        {
            _counter++;
            Console.WriteLine($"Counter: {_counter}");
        }
    }
}
lock

 

 

2024-08-13 22:14:14【出处】:https://www.cnblogs.com/INetIMVC/p/18330485

=======================================================================================

标签:Console,c#,lock,void,counter,共享资源,static,new,多线程
From: https://www.cnblogs.com/mq0036/p/18357813

相关文章

  • CF1393B Applejack and Storages 题解
    ProblemSolution注意到能拼出时必须要存在\(2\)组及以上的四个相同的木棍,或者\(1\)组及以上的四个相同的木棍和除此之外的\(2\)组及以上的两个相同的木棍。同时又注意到\(a_i\)很小,所以可以用桶统计,同时实时更新四个相同木棍的组数和两个相同木棍的组数即可。Code#in......
  • HDU-ACM 2024 Day3
    T1004游戏(HDU7460)注意到对于两个人,他们\(t\)轮后能力值相同的概率只与他们初始时的能力差有关,所以我们先\(\text{FFT}\)求出\(|a_i-a_j|=k\)的\((i,j)\)对数。构造多项式\(F(x)=(p_1x^2+p_2+p_3x)\),其中\(p_1,p_2,p_3\),分别表示在一轮中两个人相对......
  • [MVG] 鲁棒估计: RANSAC & 鲁棒核函数
    https://zhuanlan.zhihu.com/p/62175983在VSLAM中,我们首先构造3D-3D、3D-2D、2D-2D匹配,然后据此去估计相机的运动。完美估计需要完美的匹配,但实际的匹配中往往存在很多错误。如何消除或者降低错误匹配的影响呢?一种方法是选择那些正确的匹配进行估计(RANSAC),另一种是降低那些错误匹......
  • CF895B XK Segments 题解 二分
    题目链接:https://codeforces.com/problemset/problem/895/B题目大意给你一个长度为\(n\)的数列\(a_1,a_2,\ldots,a_n\)。求数列中存在多少个不同的下标对\((i,j)\)满足如下条件:\(a_i\lea_j\)并且恰好有\(k\)个整数\(y\)满足\(a_i\ley\lea_j\)且\(y\)......
  • Datawhale X 魔搭 AI夏令营 AIGC方向 Task2
    代码逐行解析先记录一下baseline代码通义千问生成的逐行解析:#安装Data-Juicer和DiffSynth-Studio!pipinstallsimple-aesthetics-predictor#安装simple-aesthetics-predictor!pipinstall-v-edata-juicer#安装data-juicer!pipuninstallpytorch-lightning-y#......
  • Google和Microsoft Edge网页插件推荐(附获取方法)
    1.插件获取方式MicrosoftEdge:找到拓展图标,点击获取MicrosoftEdge扩展:Google:在Google网页右上角找到Extensions图标,选择Manageextensions在Manageextensions中选择ChromeWebStore,打开插件商店界面。在商店搜素栏即可查询自己需要的插件。在下载插件之后,点击右......
  • JDBC在java代码中的使用
    声明对于数据库的增删改查,在使用jdbc的过程中分二类,查(DQL)语句和增,删,改(DML语句)他们的整体都分为以下五部分,只是DQL语句多了数据的处理部分。在使用之前需要导入相关的jar包 1,加载驱动器(非必要,但是建议手动加载养成好习惯)2,创建连接3,创建会话4,执行会话5,关闭会话1,数据......
  • 春秋云境 | 逻辑漏洞 | CVE-2022-23134
    目录靶标介绍开启靶场获取flag靶标介绍ZabbixSiaZabbix是拉脱维亚ZabbixSIA(ZabbixSia)公司的一套开源的监控系统。该系统支持网络监控、服务器监控、云监控和应用监控等。Zabbix存在安全漏洞,该漏洞源于在初始设置过程之后,setup.php文件的某些步骤不仅可以由超级......
  • 春秋云境 | 逻辑漏洞 | CVE-2020-13933
    靶标介绍<p>ApahceShiro由于处理身份验证请求时出错存在权限绕过漏洞,远程攻击者可以发送特制的HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。</p>开启靶场发现不管拿点哪里都是登录页面,发现登录框那里写着flag在/admin里访问之后并没有反应,在后......
  • C语言——指针(数组,函数)
    通过指针引用数组数组元素的指针数组指针:数组中的第一个元素的地址,也就是数组的首地址指针数组:用来存放数组元素地址的数组(存放数组元素指针的变量),称之为指针数组。eg://定义一个一维数组inta[]={1,4,9};//使用指针变量存储数组的第一个元素的首地址,也就是数组......