C# 实现控制后台三个线程交替输出ABC的方法

本文探讨了多线程环境下实现ABC字符循环输出的两种方法:使用共享变量配合锁机制和利用信号量(AutoResetEvent)进行线程间的精细控制。通过具体代码示例,展示了如何确保线程间正确同步,避免竞态条件,实现预期的输出序列。

问题:后台有三个线程,分别循环输出A,B,C 实现使得屏幕交替输出ABC.

1.第一种方法比较简单,使用lock(obj),先声明一个多线程共享变量 比如int n-1;在lock中检查n的值,
if(n==1) 输出A,并将n 赋值2,否则,空转。在第二个后台线程中 if(n==2)输出B,j将n=3
.一次类推,这样的虽然结果是输出了ABC 但是感觉方法并不优雅

2.方法2 采用信号量的办法,先将所有的线程进行阻塞,然后给A发送信号量,使得A线程输出一次A,接下来A向B发送信号量,然后A继续阻塞,B线程接受到信号量后输出一次B,向C发送信号量,继续阻塞
一次,以此类推

 class Program
    {
        //定义三个信号量对三个线程进行控制
        static AutoResetEvent AautoResetEvent = new AutoResetEvent(false);
        static AutoResetEvent BautoResetEvent = new AutoResetEvent(false);
        static AutoResetEvent CautoResetEvent = new AutoResetEvent(false);
        static void ShowA()
        {
            for(int i=0;i<10;i++)
            {
                AautoResetEvent.WaitOne();
                Console.Write("A");
                BautoResetEvent.Set();
            }
        }
        static void ShowB()
        {
            for (int i = 0; i < 10; i++)
            {
                BautoResetEvent.WaitOne();
                Console.Write("B");
                CautoResetEvent.Set();
            }
        }
        static void ShowC()
        {
            for (int i = 0; i < 10; i++)
            {
                CautoResetEvent.WaitOne();
                Console.Write("C");
                AautoResetEvent.Set();
            }
        }
        static void Main(string[] args)
        {
            Task.Run(()=>ShowA());
            Task.Run(() => ShowB());
            Task.Run(() => ShowC());
            AautoResetEvent.Set();
            Console.ReadLine();
        }
    }

AutoResetEvent 在Set后,waitOne 会接受到信号量,继续执行,并且自动执行Reset,将其状态更改为非终止状态,使得线程在执行到waitOne()时,会继续阻塞,等待信号量的到来
ManuResetEvent,在Set后,WaitOne接受到信号量,继续执行,使得其状态更改为终止状态,即waitOne()不会再此阻塞线程,除非手动调用Reset()
ManuReset会使的所有的线程继续执行,waitOne()不再阻塞,二AutoReset只会使得第一个阻塞的线程执行,终结原因还是在于ManuReset不会自动Reset,在终止状态时,waitOne()当然无法阻塞当前线程的运行。

在实际中使用AutoReset会更多一些,因为我们的需求一般都是在WaitOne() 线程阻塞,直到接受到信号量。在下次再次碰到waitOne()时,再次阻塞,等待信号量。

1. 线程基础概念 • 进程与线程:一个程序对应一个进程,程序启动时默认有一个主线程 • 主线程:程序的主执行通道,Main方法在主线程中运行 • 多线程优势:避免I/O等耗时操作阻塞主线程 2. 线程创建方式 ```c# // 方式1:传入方法委托 Thread t = new Thread(TestMethod); // 方式2:使用Lambda表达式 Thread t = new Thread(() => { Console.WriteLine("箭头函数的线程"); }); // 方式3:带参数的线程 Thread t2 = new Thread((a) => { Console.WriteLine("参数的线程:" + a); }); t2.Start("abc"); ``` 3. 线程操作方法 • thread.Start():启动线程 ```c# // 启动线程 thread.Start(); ``` • thread.Name:设置/获取线程名称 ```c# // 设置/获取线程名称 thread.Name = "分线程"; string name = thread.Name; ``` • Thread.CurrentThread:获取当前线程 ```c# // 获取当前线程 Thread current = Thread.CurrentThread; Console.WriteLine("当前线程名称: " + current.Name); ``` • Thread.Sleep(毫秒):线程休眠,降低执行频率 ```c# // 线程休眠(降低执行频率) Thread.Sleep(1000); // 休眠1000毫秒(1秒) ``` 3. 线程控制 • thread.Abort():终止线程(不推荐使用) • thread.Suspend():挂起线程(已过时) • ThreadStop():自定义线程停止方法 ```c# static Thread thread; // 终止线程(不推荐使用) thread.Abort(); // 挂起线程(已过时,不推荐使用) thread.Suspend(); // 自定义线程停止方法 static void ThreadStop() { if (thread != null) { thread.Abort(); // 终止线程 thread = null; // 清空引用 } } // 更安全的线程停止方式(推荐) static bool shouldStop = false; static void SafeThreadMethod() { while (!shouldStop) { // 执行任务 Thread.Sleep(1000); } } static void SafeStop() { shouldStop = true; } ``` 3. 注意事项 • 线程需要传入委托作为执行方法 • 主线程结束时分线程可能也会终止 • 使用Thread.Sleep()可以控制线程执行频率 • 线程间共享资源需要注意同步问题
最新发布
08-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值