首页 > 作文

C#多线程系列之资源池限制

更新时间:2023-04-05 00:20:18 阅读: 评论:0

maphore、maphoreslim 类

两者都可以限制同时访问某一资源或资源池的线程数。

这里先不扯理论,我们从案例入手,通过示例代码,慢慢深入了解。

maphore 类

这里,先列出 maphore 类常用的 api。

其构造函数如下:

构造函数说明maphore(int32, int32)初始化 maphore 类的新实例,并指定初始入口数和最大并北京高考发入口数。maphore(int32, int32, string)初始化 maphore 类的新实例,并指定初始入口数和最大并发入口数,根据需要指定系统信号灯对象的名称。maphore(int32, int32, string, boolean)初始化 maphore 类的新实例,并指定初始入口数和最大并发入口数,还可以选择指定系统信号量对象的名称,以及指定一个变量来接收指示是否创建了新系武汉的天气统信号量的值。

maphore 使用纯粹的内核时间(kernel-time)方式(等待时间很短),并且支持在不同的进程间同步线程(像mutex)。

maphore 常用方法如下:

方法说明clo()释放由当前 waithandle占用的所有资源。openexisting(string)打开指定名称为信号量(如果已经存在)。relea()退出信号量并返回前一个计数。relea(int32)以指定的次数退出信号量并返回前一个计数。tryopenexisting(string, maphore)打开指定名称为信号量(如果已经存在),并返回指示操作是否成功的值。waitone()阻止当前线程,直到当前 waithandle 收到信号。waitone(int32)阻止当前线程,直到当前 waithandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。waitone(int32, boolean)阻止当前线程,直到当前的 waithandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。waitone(timespan)阻止当前线程,直到当前实例收到信号,同时使用 timespan 指定时间间隔。waitone(timespan, boolean)阻止当前线程,直到当前实例收到信号为止,同时使用 timespan 指定时间间隔,并指定是否在等待之前退出同步域。

示例

我们来直接写代码,这里使用 《原子操作 interlocked》 中的示例,现在我们要求,采用多个线程执行计算,但是只允许最多三个线程同时执行运行。

使用 maphore ,有四个个步骤:

n棱长公式ew 实例化 maphore,并设置最大线程数、初始化时可进入线程数;

使用.waitone();获取进入权限(在获得进入权限前,线程处于阻塞状态)。

离开时使用relea()释放占用。

clo()释放maphore 对象。

《原子操作 interlocked》 中的示例改进如下:

    class program    {        // 求和        private static int sum = 0;        private static maphore _pool;        // 判断十个线程是否结束了。        private static int iscomplete = 0;        // 第一个程序        static void main(string[] args)        {            console.writeline("执行程序");            // 设置允许最大三个线程进入资源池            // 一开始设置为0,就是初始化时允许几个线程进入            // 这里设置为0,后面按下按键时,可以放通三个线程            _pool = new maphore(0, 3);            for (int i = 0; i < 10; i++)            {                thread thread = new thread(new parameterizedthreadstart(addone));                thread.start(i + 1);            }            console.foregroundcolor = consolecolor.red;            console.writeline("任意按下键(不要按关机键),可以打开资源池");            console.foregroundcolor = consolecolor.white;            console.readkey();            // 准许三个线程进入            _pool.relea(3);            // 这里没有任何意义,就单纯为了演示查看结果。            // 等待所有线程完成任务            while (true)            {                if (iscomplete >= 10)                    break;                thread.sleep(timespan.fromconds(1));            }            console.writeline("sum = " + sum);            // 释放池            _pool.clo();                    }        public static void addone(object n)        {            console.writeline($"    线程{(int)n}启动,进入队列");            // 进入队列等待            _pool.waitone();            console.writeline($"第{(int)n}个线程进入资源池");            // 进入资源池            for (int i = 0; i < 10; i++)            {                interlocked.add(ref sum, 1);                thread.sleep(timespan.frommilliconds(500));            }            // 解除占用的资源池            _pool.relea();            iscomplete += 1;            console.writeline($"                     第{(int)n}个线程退出资源池");        }    }

看着代码有点多,快去运行一下,看看结果。

示例说明

实例化 maphore 使用了new maphore(0,3);,其构造函数原型为

public maphore(int initialcount, int maximumcount);

initialcount 表示一开始允许几个进程进入资源池,如果设置为0,所有线程都不能进入,要一直等资源池放通。

maximumcount 表示最大允许几个线程进入资源池。

relea()表示退出信号量并返回前一个计数。这个计数指的是资源池还可以进入多少个线程。

可以看一下下面的示例:

        private static maphore _pool;        static void main(string[] args)        {            _pool = new maphore(0, 5);            _pool.relea(5);            new thread(addone).start();            thread.sleep(timespan.fromconds(10));            _pool.clo();        }        public static void addone()        {            _pool.waitone();            thread.sleep(1000);            int count = _pool.relea();            console.writeline("在此线程退出资源池前,资源池还有多少线程可以进入?" + count);        }

信号量

前面我们学习到 mutex,这个类是全局操作系统起作用的。我们从 mutex 和 mphore 中,也看到了 信号量这个东西。

信号量分为两种类型:本地信号量和命名系统信号量。

命名系统信号量在整个操作系统中均可见,可用于同步进程的活动。局部信号量仅存在于进程内。

当 name 为 null 或者为空时,mutex 的信号量时局部信号量,否则 mutex 的信号量是命名系统信号量。

maphore 的话,也是两种情况都有。

如果使用接受名称的构造函数创建 maphor 对象,则该对象将与该名称的操作系统信号量关联。

两个构造函数:

maphore(int32, int32, string)maphore(int32, int32, string, boolean)

上面的构造函数可以创建多个表示同一命名系统信号量的 maphore 对象,并可以使用 openexisting 方法打开现有的已命名系统信号量。

我们上面使用的示例就是局部信号量,进程中引用本地 maphore 对象的所有线程都可以使用。 每个 maphore 对象都是单独的本地信号量。

maphoreslim类

maphoreslim 跟 maphore 有啥关系?

微软文档:

maphoreslim 表示对可同时访问资源或资源池的线程数加以限制的 maphore 的轻量替代。

maphoreslim 不使用信号量,不支持进程间同步,只能在进程内使用。

它有两个构造函数:

构造函数说明maphoreslim(int32)初始化 maphoreslim 类的新实例,以指定可同时授予的请求的初始数量。maphoreslim(int32, int32)初始化 maphoreslim 类的新实例,同时指定可同时授予的请求的初始数量和最大数量。

示例

我们改造一下前面 maphore 中的示例:

    c26个字母背诵顺口溜lass program    {        // 求和        private static int sum = 0;        private static maphoreslim _pool;        // 判断十个线程是否结束了。        private static int iscomplete = 0;        static void main(string[] args)        {            console.writeline("执行程序");            // 设置允许最大三个线程进入资源池    致我逝去的父亲        // 一开始设置为0,就是初始化时允许几个线程进入            // 这里设置为0,后面按下按键时,可以放通三个线程            _pool = new maphoreslim(0, 3);            for (int i = 0; i < 10; i++)            {                thread thread = new thread(new parameterizedthreadstart(addone));                thread.start(i + 1);            }            console.writeline("任意按下键(不要按关机键),可以打开资源池");            console.readkey();            //             _pool.relea(3);            // 这里没有任何意义,就单纯为了演示查看结果。            // 等待所有线程完成任务            while (true)            {                if (iscomplete >= 10)                    break;                thread.sleep(timespan.fromconds(1));            }            console.writeline("sum = " + sum);            // 释放池        }        public static void addone(object n)        {            console.writeline($"    线程{(int)n}启动,进入队列");            // 进入队列等待            _pool.wait();            console.writeline($"第{(int)n}个线程进入资源池");            // 进入资源池            for (int i = 0; i < 10; i++)            {                interlocked.add(ref sum, 1);                thread.sleep(timespan.frommilliconds(200));            }            // 解除占用的资源池            _pool.relea();            iscomplete += 1;            console.writeline($"                     第{(int)n}个线程退出资源池");        }    }

maphoreslim 不需要clo()

两者在代码上的区别是就这么简单。

区别

如果使用下面的构造函数实例化 maphor(参数name不能为空),那么创建的对象在整个操作系统内都有效。

public maphore (int initialcount, int maximumcount, string name);

maphorslim 则只在进程内内有效。

maphoreslim 类不会对waitwaitasyncrelea方法的调用强制执行线程或任务标识。

而 maphor 类,会对此进行严格监控,如果对应调用数量不一致,会出现异常。

此外,如果使用 maphoreslim(int32 maximumcount) 构造函数来实例化 maphoreslim 对象,获取其 currentcount 属性,其值可能会大于 maximumcount。 编程人员应负责确保调用一个 wait 或 waitasync 方法,便调用一个 relea。

这就好像笔筒里面的笔,没有监控,使用这使用完毕后,都应该将笔放进去。如果原先有10支笔,每次使用不放进去,或者将别的地方的笔放进去,那么最后数量就不是10了。

到此这篇关于c#多线程系列之资源池限制的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-05 00:20:16,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/89fd55b51835d00d46d5c2dbaba0e045.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C#多线程系列之资源池限制.doc

本文 PDF 下载地址:C#多线程系列之资源池限制.pdf

标签:信号量   线程   资源   示例
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图