设置首页收藏本站
开启左侧

C#程序线程的阻塞与异步中的同步问题

[复制链接]
Criss 发表于 2017-9-5 22:00:06 | 显示全部楼层 |阅读模式
.Net里提供了EventWaitHandle类来表示一个线程的同步事件。EventWaitHandle即事件等待句柄,他允许线程通过操作系统互发信号和等待彼此的信号来达到线程同步的目的。
这个类有2个子类,分别为AutoRestEevnt(自动重置)和ManualRestEvent(手动重置)。

下面是线程同步的几个方法:
(1)Reset方法:将事件状态设为非终止状态,导致线程阻塞。这里的线程阻塞是指允许其他需要等待的线程进行阻塞即让含WaitOne()方法的线程阻塞;
(2)Set方法:将事件状态设为终止状态,允许一个或多个等待线程继续。该方法发送一个信号给操作系统,让处于等待的某个线程从阻塞状态转换为继续运行,即WaitOne方法的线程不在阻塞;
(3)WaitOne方法:阻塞当前线程,直到当前的等待句柄收到信号。此方法将一直使本线程处于阻塞状态直到收到信号为止,即当其他非阻塞进程调用set方法时可以继续执行。

奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
evelec 发表于 2017-10-18 23:00:17 | 显示全部楼层
多线程并发访问同一资源或变量会造成执行混乱、结果将产生不可预知的数据损坏。

无关线程:        线程之间没有任何联系,各自独立运行,互不干扰。
相关线程:        线程之间有联系,两个线程共享资源,等。
临界资源:        多个线程共享的资源。
临界区:        访问临界资源的代码
同步:                两个线程协同工作才能共同完成一项任务的情况
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
evelec 发表于 2017-10-18 23:02:40 | 显示全部楼层
* 终止状态:            WaitOne()允许线程访问下边的语句
         * 非终止状态:        WaitOne()阻塞线程,不允许线程访问下边的语句
         *
         * Set()方法:        把非终止状态改为终止状态用, WaitOne()允许线程访问下边的语句
         * Reset()方法:        把终止状态改为非终止状态用, WaitOne()阻塞线程,不允许线程访问下边的语句
         *
         * //true:        设置终止状态。首次不会被WaitOne()阻塞,下次执行WaitOne()才会被阻塞
         * //false:设置非终止状态。遇到WaitOne()立即阻塞所在的一个或多个线程
         *
         * AutoResetEvent are_thread = new AutoResetEvent(true);
         * //1.AutoResetEvent,调用一次Set()只能继续一个阻塞线程
         * //2.AutoResetEvent,调用Set()后自动Reset()
         *
         * ManualResetEvent mre_thread = new ManualResetEvent(false);
         * //1.ManualResetEvent,调用一次Set()允许继续全部阻塞线程,这是和AutoResetEvent的区别
         * //2.ManualResetEvent,调用 Reset(),将信号设置为非终止状态,在非终止状态线程中调用WaitOne()阻塞线程。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
evelec 发表于 2017-10-18 23:03:46 | 显示全部楼层
此外,EventWaitHandle类还拥有两种模式,AutoReset 和 ManualReset 模式:
var auto = new EventWaitHandle (false);
var auto = new EventWaitHandle (false, EventResetMode. AutoReset);
与AutoResetEvent类似,ManualResetEvent可以使用两种方式构造:
var manual = new ManualResetEvent (false);
var manual = new EventWaitHandle (false, EventResetMode.ManualReset);
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
evelec 发表于 2017-10-18 23:09:51 | 显示全部楼层
class Program
    {
        static ManualResetEvent _mre = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("输入1为Set()   开始运行");
            Console.WriteLine("输入2为Reset() 暂停运行");

            Thread[] _threads = new Thread[3];
            for (int i = 0; i < _threads.Count(); i++)
            {
                _threads[i] = new Thread(ThreadRun);
                _threads[i].Start();
            }

            while (true)
            {
                switch (Console.ReadLine())
                {
                    case "1":
                        Console.WriteLine("开始运行");
                        _mre.Set();                        
                        break;
                    case "2":
                        Console.WriteLine("暂停运行");
                        _mre.Reset();                        
                        break;
                    default:
                        break;
                }
            }
           
        }

        static void ThreadRun()
        {
            int _threadID = 0;
            while (true)
            {
                _threadID = Thread.CurrentThread.ManagedThreadId;
                Console.WriteLine("当前线程:" + _threadID);
                Thread.Sleep(TimeSpan.FromSeconds(2));
                _mre.WaitOne();
            }
        }

        /*
         * 终止状态:            WaitOne()允许线程访问下边的语句
         * 非终止状态:        WaitOne()阻塞线程,不允许线程访问下边的语句
         *
         * Set()方法:        把非终止状态改为终止状态用, WaitOne()允许线程访问下边的语句
         * Reset()方法:        把终止状态改为非终止状态用, WaitOne()阻塞线程,不允许线程访问下边的语句
         *
         * //true:        设置终止状态。首次不会被WaitOne()阻塞,下次执行WaitOne()才会被阻塞
         * //false:设置非终止状态。遇到WaitOne()立即阻塞所在的一个或多个线程
         *
         * AutoResetEvent are_thread = new AutoResetEvent(true);
         * //1.AutoResetEvent,调用一次Set()只能继续一个阻塞线程
         * //2.AutoResetEvent,调用Set()后自动Reset()
         *
         * ManualResetEvent mre_thread = new ManualResetEvent(false);
         * //1.ManualResetEvent,调用一次Set()允许继续全部阻塞线程,这是和AutoResetEvent的区别
         * //2.ManualResetEvent,调用 Reset(),将信号设置为非终止状态,在非终止状态线程中调用WaitOne()阻塞线程。
         */
    }
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
yzzsjc136 发表于 2018-2-1 15:32:58 | 显示全部楼层

好东西,分享一下
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表