SemaphoreSlim

https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx

Represents a lightweight alternative to Semaphore that limits the number of threads that can access a resource or pool of resources concurrently.

Remarks

Semaphores are of two types: local semaphores and named system semaphores.

The former is local to an app. The latter is visible throughout the operating system and is suitable for inter-process synchronization.

The SemaphoreSlim is a lightweight alternative to the Semaphore class that doesn't use Windows kernel semaphores.

Unlike the Semaphore class, the SemaphoreSlim class doesn’t support named system semaphores.

You can use it as a local semaphore only.

The SemaphoreSlim class is the recommended semaphore for synchronization within a single app.

 

A lightweight semaphore controls access to a pool of resources that is local to your application.

When you instantiate a semaphore, you can specify the maximum number of threads that can enter the semaphore concurrently.

You also specify the initial number of threads that can enter the semaphore concurrently. This defines the semaphore's count.

 

The count is decremented each time a thread enters the semaphore, and incremented each time a thread releases the semaphore.

To enter the semaphore, a thread calls one of the Wait or WaitAsync overloads.

To release the semaphore, it calls one of the Release overloads.

When the count reaches zero, subsequent calls to one of the Wait methods block until other threads release the semaphore.

If multiple threads are blocked, there is no guaranteed order, such as FIFO or LIFO, that controls when threads enter the semaphore.

The basic structure for code that uses a semaphore to protect resources is:

' Enter semaphore by calling one of the Wait or WaitAsync methods.
SemaphoreSlim.Wait()
' 
' Execute code protected by the semaphore. 
'
SemaphoreSlim.Release()

When all threads have released the semaphore, the count is at the maximum value specified when the semaphore was created.

The semaphore's count is available from the CurrentCount property.

 

Important

The SemaphoreSlim class doesn’t enforce thread or task identity on calls to the WaitWaitAsync, and Release methods.

In addition, if the SemaphoreSlim(Int32) constructor is used to instantiate the SemaphoreSlim object, the CurrentCount property can increase beyond the value set by the constructor.

It is the programmer's responsibility to ensure that calls to Wait or WaitAsync methods are appropriately paired with calls to Release methods.

 

Example

The following example creates a semaphore with a maximum count of three threads and an initial count of zero threads.

The example starts five tasks, all of which block waiting for the semaphore.

The main thread calls the Release(Int32) overload to increase the semaphore count to its maximum, which allows three tasks to enter the semaphore.

Each time the semaphore is released, the previous semaphore count is displayed. Console messages track semaphore use.

The simulated work interval is increased slightly for each thread to make the output easier to read.

复制代码
public class Example
    {
        private static SemaphoreSlim semaphoreSlim;

        private static int padding;

        internal static void Method()
        {
            //Create the semaphore.
            semaphoreSlim = new SemaphoreSlim(0, 3);
            Console.WriteLine("{0} tasks can enter the semaphore.", semaphoreSlim.CurrentCount);

            Task[] tasks = new Task[5];

            // Create and start five numbered tasks.
            for (int i = 0; i <= 4; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    // Each task begins by requesting the semaphore.
                    Console.WriteLine("Task {0} begins and waits for the semaphore.", Task.CurrentId);
                    semaphoreSlim.Wait();

                    Interlocked.Add(ref padding, 100);

                    Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId);

                    // The task just sleeps for 1+ seconds.
                    Thread.Sleep(1000 + padding);

                    Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.", Task.CurrentId, semaphoreSlim.Release());
                });
            }

            // Wait for half a second, to allow all the tasks to start and block.
            Thread.Sleep(500);

            // Restore the semaphore count to its maximum value.
            Console.Write("Main thread calls Release(3) --> ");
            semaphoreSlim.Release(3);
            Console.WriteLine("{0} tasks can enter the semaphore.", semaphoreSlim.CurrentCount);
            // Main thread waits for the tasks to complete.
            Task.WaitAll(tasks);

            Console.WriteLine("Main thread exits.");
        }
    }
复制代码

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(1251)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示