前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#Semaphore&SemaphoreSlim

C#Semaphore&SemaphoreSlim

作者头像
JusterZhu
发布2023-11-03 15:49:36
2840
发布2023-11-03 15:49:36
举报
文章被收录于专栏:JusterZhuJusterZhu

1. Semaphore

Semaphore 是一个.NET的线程同步对象,可以用来控制对资源的并行访问数量。Semaphore 在计算机科学中是一个很重要的概念,用于解决多线程编程中的各种问题。

基本上,Semaphore 是一个计数器,表示一个特定的资源可以被多少个线程同时访问。当一个线程试图进入一个受 Semaphore 控制的区块时,如果当前的计数大于零,则此线程可以继续执行,并且计数器会减一。如果计数器为零,则该线程将被阻塞,直到其他线程释放资源(计数器增加)。

在.NET中,你可以使用 System.Threading.Semaphore 类实现这个功能。

以下是一个简单的示例:

代码语言:javascript
复制
// Creates a Semaphore object that can support up to three threads, with an initial count of zero threads.
Semaphore sem = new Semaphore(0, 3);

// Increment the semaphore count by three, allowing three threads to enter.
sem.Release(3);

// The current thread tries to enter the semaphore. If the count is greater than zero, it succeeds and the count is decremented by one.
sem.WaitOne();

Semaphore跨进程使用

使用 Semaphore 实现进程间同步的一种方式是使用具有特定名称的 Semaphore。在一个进程中创建命名的 Semaphore 后,可以在其他进程中通过名称打开并使用该 Semaphore

以下是创建和使用命名 Semaphore 的示例:

进程1:

代码语言:javascript
复制
// 创建一个具有最大计数 3 和初始计数 0 的命名 Semaphore
Semaphore semaphore = new Semaphore(0, 3, "MySemaphore");

// 允许三个线程或进程访问资源
semaphore.Release(3);

// ... 进行其他工作 ...

// 不再需要 Semaphore 时关闭它
semaphore.Close();

进程2:

代码语言:javascript
复制
// 在另一个进程中打开已经存在的命名 Semaphore
Semaphore existingSemaphore;
try
{
    existingSemaphore = Semaphore.OpenExisting("MySemaphore");
}
catch(System.Threading.WaitHandleCannotBeOpenedException)
{
    Console.WriteLine("The named semaphore does not exist.");
    return;
}

// 尝试进入 semaphore. 如果计数器大于零,则成功并将计数器减一
existingSemaphore.WaitOne();

// ... 进行工作 ...

// 完成工作后,释放访问权,以便其他等待的线程或进程可以进入
existingSemaphore.Release();

// ... 进行其他工作 ...

// 不再需要 Semaphore 时关闭它
existingSemaphore.Close();

这样便实现了两个或更多进程之间的同步。每个需要访问共享资源的进程都会调用 WaitOne() 方法。如果 Semaphore 的当前计数大于零,那么线程就可以继续执行并将 Semaphore的计数减一。如果计数为零,那么此线程将被阻塞,直到其他线程调用 Release() 方法增加计数。

2. SemaphoreSlim

SemaphoreSlim 是.NET 4.5引入的一个轻量级版本的 Semaphore,它主要用于在同一台机器上的任务和线程间进行同步,在性能上比 Semaphore 要好,但不能跨进程使用。

除了性能提升之外,SemaphoreSlim 还提供了异步支持,通过 WaitAsync 方法可以非阻塞地等待进入 Semaphore。

以下是一个简单的使用示例:

代码语言:javascript
复制
// Creates a SemaphoreSlim object that can support up to three threads, with an initial count of zero threads.
SemaphoreSlim semSlim = new SemaphoreSlim(0, 3);

// Increment the semaphore count by three, allowing three tasks or threads to enter.
semSlim.Release(3);

// The current task or thread tries to enter the semaphore. 
// If the count is greater than zero, it succeeds and the count is decremented by one.
await semSlim.WaitAsync();

在使用完 SemaphoreSemaphoreSlim 后,应调用 Release 方法以便其它等待的线程或任务可以进入。

Task中使用SemaphoreSlim

在这个示例中,SemaphoreSlim 被用来限制在任意时刻只有一个 Task 可以进入临界区。其他尝试进入临界区的 Task 将被挂起,直到当前 Task 执行完毕并释放 SemaphoreSlim。

代码语言:javascript
复制
SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

List<Task> tasks = new List<Task>();

for (int i = 0; i < 10; i++)
{
    tasks.Add(Task.Run(async () =>
    {
        await semaphore.WaitAsync();

        try
        {
            // Critical section.
            Console.WriteLine("Task {0} in critical section.", Task.CurrentId);
            await Task.Delay(1000); // Simulate some work.
        }
        finally
        {
            Console.WriteLine("Task {0} leaving critical section.", Task.CurrentId);
            semaphore.Release();
        }
    }));
}

await Task.WhenAll(tasks);

Semaphore 和 SemaphoreSlim 区别

  • SemaphoreSlim 有更好的性能和内存效率,但只能在同一进程中使用。
  • Semaphore 可以跨进程使用,但性能和内存效率不如 SemaphoreSlim
  • SemaphoreSlim 支持异步操作。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Semaphore
    • Semaphore跨进程使用
    • 2. SemaphoreSlim
      • Task中使用SemaphoreSlim
        • Semaphore 和 SemaphoreSlim 区别
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档