C# Semaphore 信号量 锁 简单理解

信号量(Semaphore)

Semaphore 一般译作 信号量,它也是一种线程同步工具,主要用于多个线程对共享资源进行并行操作的一种工具类。它代表了一种许可的概念,是否允许多线程对同一资源进行操作的许可,使用 Semaphore 可以控制并发访问资源的线程个数。


Semaphore 的使用场景

1、主要用于流量控制,比如数据库连接,同时使用的数据库连接会有数量限制,数据库连接不能超过一定的数量,当连接到达了限制数量后,后面的线程只能排队等前面的线程释放数据库连接后才能获得数据库连接。
2、 信号量:是进程间(线程间)同步用的,一个进程(线程)完成了某一个动作就通过信号量告诉别的进程(线程),别的进程(线程)再进行某些动作。有二值和多值信号量之分。

它与的互斥锁区别是 互斥锁:是线程间互斥用的,一个线程占用了某一个共享资源,那么别的线程就无法访问,直到这个线程离开,其他的线程才开始可以使用这个共享资源。可以把互斥锁看成二值信号量。  

引发的问题

信号量存在的优先级翻转问题

优先级反转,是指在使用信号量时,可能会出现的这样一种不合理的现象,即:

高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。-- 从现象上来看,好像是中优先级的任务比高优先级任务具有更高的优先权。

具体来说:当高优先级任务正等待信号量(此信号量被一个低优先级任务拥有着)的时候,一个介于两个任务优先之间的中等优先级任务开始执行——这就会导致一个高优先级任务在等待一个低优先级任务,而低优先级任务却无法执行类似死锁的情形发生。

主要方法

Semaphore(1, 4):默认运行信号量之后就可以释放一条线程进入临界资源。手动设置Release的一次最大个数是4条线程,临界区最大的线程数是4.当一次释放的线程超过等待的资源数就会报错

WaitOne()阻塞线程,等灯来
Release(N) 同时放行条线程进入资源区,最大不能超过初始化设定的maximumCount
Close()释放所有

使用方式1

有10个线程,同时只执行4条线程,每完成一个就Release一个,等待中的就补上去

 

 代码如下:

该代码会正常执行完成,并且释放所有线程,因为初始化话new Semaphore(1, 4)时候已经设置默认释放一条线程,这条线程执行完成后road.Release();又释放下一条。依次释放完所有线程。
 
Semaphore road = new Semaphore(1, 4);
for(int i = 0; i < 10; i++)
{
    new Thread(obj =>
    {
        int se = (int)obj;
        Console.WriteLine(se);
        road.WaitOne();

        Console.WriteLine("release{0}",obj);
        road.Release();//该线程执行完毕,后再释放一个线程
    }

    ).Start(i);



}
Thread.Sleep(1000);
//该代码会正常执行完成,并且释放说有线程,因为初始化话new Semaphore(1, 4)时候已经设置默认释放一条线程,这条线程执行完成后road.Release();又释放下一条。依次释放完所有线程。

 另外,信号量是内核对象可以再多个进程中使用。可以给信号量设置一个名称,这个名称是操作系统可见的,因此,可以使用这些信号量来协调跨进程边界的资源使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Semaphore2
{
    class Program
    {
        static void Main(string[] args)
        {
            Semaphore seamphore = new Semaphore(5, 5, "SemaphoreExample");

            seamphore.WaitOne();
            Console.WriteLine("Seamphore 1");
            seamphore.WaitOne();
            Console.WriteLine("Seamphore 2");
            seamphore.WaitOne();
            Console.WriteLine("Seamphore 3");

            Console.ReadLine();
            seamphore.Release(3);
        }
    }
}

复制代码

 运行两个这样的程序,你将看到这样的结果,在第二个运行的示例中,会将线程阻塞在第三个信号量

 

 

posted @ 2022-01-17 05:39  小林野夫  阅读(1594)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/