"C#用两个线程交替打印1-100的五种方法"是.NET工程师面试多线程常考的试题之一,主要考察对C#语法和对多线程的熟悉程度。本文将用5种方法实现这个面试题。
方法1:使用Mutex或lock
这种方法涉及使用Mutex或lock对象来同步两个线程。其中一个线程负责打印偶数,另一个线程负责打印奇数。线程在执行任务之前会锁定共享的Mutex或lock对象,以确保每个线程执行任务时只有一个线程能够访问共享资源。代码如下:.
class Program{static Mutex mutex = new Mutex();static int count = 1;static void Main(string[] args){Thread t1 = new Thread(PrintOddNumbers);Thread t2 = new Thread(PrintEvenNumbers);t1.Start();t2.Start();t1.Join();t2.Join();Console.ReadLine();}static void PrintOddNumbers(){while (count <= 100){mutex.WaitOne();if (count % 2 == 1){Console.WriteLine("Thread 1: " + count);count++;}mutex.ReleaseMutex();}}static void PrintEvenNumbers(){while (count <= 100){mutex.WaitOne();if (count % 2 == 0){Console.WriteLine("Thread 2: " + count);count++;}mutex.ReleaseMutex();}}}
方法2:使用AutoResetEvent
AutoResetEvent是一种线程同步机制,允许一个线程等待另一个线程发出信号来继续执行。其中一个线程负责打印奇数,另一个线程负责打印偶数。当一个线程完成打印任务时,它发出信号以唤醒另一个线程来继续执行。
class Program{static AutoResetEvent oddEvent = new AutoResetEvent(false);static AutoResetEvent evenEvent = new AutoResetEvent(false);static int count = 1;static void Main(string[] args){Thread t1 = new Thread(PrintOddNumbers);Thread t2 = new Thread(PrintEvenNumbers);t1.Start();t2.Start();t1.Join();t2.Join();Console.ReadLine();}static void PrintOddNumbers(){while (count <= 100){if (count % 2 == 1){Console.WriteLine("Thread 1: " + count);count++;evenEvent.Set();oddEvent.WaitOne();}}}static void PrintEvenNumbers(){while (count <= 100){if (count % 2 == 0){Console.WriteLine("Thread 2: " + count);count++;oddEvent.Set();evenEvent.WaitOne();}}}//欢迎关注公众号“DOTNET开发跳槽”,关注可获得海量面试题
方法3:使用Monitor
Monitor是C#中的一种同步机制,类似于Mutex。其中一个线程负责打印奇数,另一个线程负责打印偶数。线程在执行任务之前会锁定共享的Monitor对象,以确保每个线程执行任务时只有一个线程能够访问共享资源。
class Program{static object lockObj = new object();static int count = 1;static void Main(string[] args){Thread t1 = new Thread(PrintOddNumbers);Thread t2 = new Thread(PrintEvenNumbers);t1.Start();t2.Start();t1.Join();t2.Join();Console.ReadLine();}static void PrintOddNumbers(){while (count <= 100){lock (lockObj){if (count % 2 == 1){Console.WriteLine("Thread 1: " + count);count++;}}}}static void PrintEvenNumbers(){while (count <= 100){lock (lockObj){if (count % 2 == 0){Console.WriteLine("Thread 2: " + count);count++;}}}}}
方法4:使用信号量Semaphore
Semaphore是一种同步机制,允许多个线程同时访问共享资源。其中一个线程负责打印奇数,另一个线程负责打印偶数。线程在执行任务之前会等待信号量,以确保每个线程只有在获得信号量之后才能访问共享资源。
class Program{static Semaphore semaphore = new Semaphore(1, 1);static int count = 1;static void Main(string[] args){Thread t1 = new Thread(PrintOddNumbers);Thread t2 = new Thread(PrintEvenNumbers);t1.Start();t2.Start();t1.Join();t2.Join();Console.ReadLine();}static void PrintOddNumbers(){ //注意 这里是99,否则会出现101while (count <= 99){semaphore.WaitOne();if (count % 2 == 1){Console.WriteLine("Thread 1: " + count);count++;}semaphore.Release();}}static void PrintEvenNumbers(){while (count <= 100){semaphore.WaitOne();if (count % 2 == 0){Console.WriteLine("Thread 2: " + count);count++;}semaphore.Release();}}}
方法5:使用Task和async/await
在C#中,使用Task和async/await关键字可以轻松地在两个线程之间切换执行。其中一个线程负责打印奇数,另一个线程负责打印偶数。线程在执行任务之前使用async/await等待异步任务完成,以确保每个线程只在异步任务完成后才访问共享资源。
class Program{static int count = 1;static void Main(string[] args){Task.Run(PrintOddNumbers);// 这里改成这个也可以// var thread1 = new Thread(PrintOddNumbers);Task.Run(PrintEvenNumbers);Console.ReadLine();}//如果用Thread改成同步方法static async Task PrintOddNumbers(){while (count <= 100){if (count % 2 == 1){Console.WriteLine("Thread 1: " + count);count++;//如果用Thread这里改成 Thread.Sleep(1);await Task.Delay(1);}}}static async Task PrintEvenNumbers(){while (count <= 100){if (count % 2 == 0){Console.WriteLine("Thread 2: " + count);count++;await Task.Delay(1);}}}//欢迎关注公众号“DOTNET开发跳槽”,关注可获得海量面试题
五种效果如下:

考察的知识点