首页 > 编程语言 >面试常考:C#用两个线程交替打印1-100的五种方法

面试常考:C#用两个线程交替打印1-100的五种方法

时间:2023-12-18 22:22:06浏览次数:37  
标签:Thread C# 常考 打印 t1 static 线程 PrintOddNumbers

面试常考:C#用两个线程交替打印1-100的五种方法

面试常考:C#用两个线程交替打印1-100的五种方法

翔星 翔星 有10年+工作经验,高级软件工程师,可以解决各种问题   你经常看 TA 的内容

"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);Threadt2=newThread(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);Threadt2=newThread(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);Threadt2=newThread(PrintEvenNumbers); t1.Start();t2.Start(); t1.Join(); t2.Join(); Console.ReadLine(); } static void PrintOddNumbers() { //注意 这里是99,否则会出现101 while (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);//这里改成这个也可以//varthread1=newThread(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开发跳槽”,关注可获得海量面试题

五种效果如下:

 

 

以上五种方法各有优缺点,没有一种方法是绝对最优的,取决于应用场景和要求。以下是对五种方法的简单比较和说明:

1、使用ManualResetEventWaitHandle:这种方法在实现上较为简单,但是由于线程必须互斥地访问共享资源,因此会导致性能瓶颈。此外,使用ManualResetEventWaitHandle需要频繁调用WaitOne和Set方法,可能会降低应用程序的响应能力。

2、使用AutoResetEventWaitHandle:这种方法在实现上比较简单,而且使用AutoResetEventWaitHandle可以避免性能瓶颈问题。然而,它仍然需要频繁调用WaitOne和Set方法,可能会降低应用程序的响应能力。

3、使用锁:使用锁可以避免性能瓶颈问题,因为同一时间只有一个线程可以访问共享资源。但是,锁可能会导致线程死锁和性能下降的问题,因此需要小心使用。

4、使用信号量Semaphore:这种方法可以避免性能瓶颈问题,并允许多个线程同时访问共享资源。Semaphore还可以设置多个许可证,以控制并发线程的数量。然而,使用Semaphore可能会使代码变得更加复杂,因此需要小心使用。

5、使用Task和async/await:这种方法可以避免性能瓶颈问题,并且使用Task和async/await可以使代码更加简洁易懂。但是,它可能会对内存和CPU产生额外的开销,因为需要在任务之间频繁地切换上下文。

综上所述,选择哪种方法取决于应用程序的要求和程序员的个人偏好。如果应用程序需要更好的性能,则应该使用锁或信号量;如果应用程序需要更简洁易懂的代码,则应该使用Task和async/await。

考察的知识点

1、C#编程语言和语法:实现多线程程序需要熟悉C#编程语言和语法,包括线程的创建和管理、共享资源的访问和同步等方面的知识。

2、多线程编程:多线程编程是指同时运行多个线程的编程模型,它可以提高应用程序的性能和响应能力。多线程编程需要考虑线程的同步、共享资源的访问、线程间的通信等问题。

3、线程同步机制:线程同步机制是指用于控制多个线程访问共享资源的机制,常用的线程同步机制包括锁、信号量、事件等。

4、异步编程:异步编程是指不阻塞线程并且在完成任务后通知线程的编程模型,它可以提高应用程序的响应能力和性能。异步编程需要熟悉异步和await关键字、Task和Task<T>等类型、async和await方法等概念。

参考:chatGPT

 

版权声明:本文来源于网友收集或网友供稿,仅供学习交流之用,如果有侵权,请转告小编或者留言,本公众号立即删除。

关注公众号:DotNet开发跳槽❀觉得不错,请点个在看呀

标签:Thread,C#,常考,打印,t1,static,线程,PrintOddNumbers
From: https://www.cnblogs.com/sexintercourse/p/17912518.html

相关文章

  • AtCoder Beginner Contest 324
    C-ErrorCorrection大意是:给定一个字符串a,以及一组字符串,如果字符串与a满足以下之一即可我写的有点麻烦。。#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ intn; cin>>n; strings; cin>>s; vector<int>ans; for(inti=1;i<=n;i++){ stringt; ci......
  • BIgdataAIML-IBM-A neural networks deep dive - An introduction to neural networks
    https://developer.ibm.com/articles/cc-cognitive-neural-networks-deep-dive/ByM.TimJones,PublishedJuly23,2017Neuralnetworkshavebeenaroundformorethan70years,buttheintroductionofdeeplearninghasraisedthebarinimagerecognitionand......
  • 发布 VectorTraits v1.0, 它是C#下增强SIMD向量运算的类库
    发布VectorTraitsv1.0,它是C#下增强SIMD向量运算的类库zyl910吃瓜群众​关注 你经常看C#话题的内容发布VectorTraitsv1.0,它是C#下增强SIMD向量运算的类库VectorTraits:SIMDVectortypetraitsmethods(SIMD向量类型的特征方法).N......
  • 符号执行manticore工具演练之发现缓冲区溢出漏洞
    符号执行之manticore工具演练参考资料:SANSSEC554https://docs.soliditylang.org/en/v0.8.0/ziion虚拟机:区块链智能合约中的kali(ziion涵盖演练中所以提及到的工具)动静态之分IDA是静态分析工具,常用于检测脆弱性;manticore是动态分析工具,常用于编写漏洞利用(符号执行:即执......
  • C# 读写 Excel 四种方案(OpenXml、NPOI、EPPlus、Spire.Office)
    C#读写Excel四种方案(OpenXml、NPOI、EPPlus、Spire.Office)翔星有10年+工作经验,高级软件工程师,可以解决各种问题​关注 你经常看TA的内容前言在项目中需要使用C#读写Excel,每天定时将数据输出到Excel表格中。在参考了很多的方案后,找到了4......
  • keys_async_drv.c
    HelloWorld/*按键设备中断触发,poll机制非阻塞,定时器使用方式*///keys按键设备异步通知方式驱动文件keys_async_drv.c#include<linux/module.h>#include<linux/kernel.h>#include<linux/fs.h>#include<linux/init.h>#include<linux/mutex.h>#include<l......
  • 这10个TypeScript高级技巧,助你成为更好的开发者!
    这10个TypeScript高级技巧,助你成为更好的开发者!前端学习站 ​关注他 在使用了一段时间的Typescript之后,我深深地感受到了Typescript在大中型项目中的必要性。可以提前避免很多编译期的bug,比如烦人的拼写问题。并且越来越多的包都在使用TS,所以学习它势在必行......
  • 如何在 C# 中使用 投影(Projection)
    如何在C#中使用投影(Projection)一线码农 ​关注他 你浏览过TA的个人主页投影(Projection)是一种可以将查询结果进行 塑性 的一种操作,你可以使用 投影 将一个object转成仅包含你需要属性的新对象,这篇文章中,我们就一起看看如何使用投影功......
  • Keepalived+Nginx+Tomcat配置高可用负载均衡系统示例
    前言目前生产环境的配置越来越多的使用云服务了,同时负载均衡也基本转向了云厂商提供的服务,但对于绝大多数应用来说,自建集群可能在费用上要更便宜一些,这篇文章也是之前整理的,再次新瓶装旧酒分享给各位。此示例演示在不使用docker的情况下配置负载均衡,内容keepalived+nginx+tomcat......
  • 让你 React 组件水平暴增的 5 个技巧
    让你React组件水平暴增的5个技巧神说要有光​ ​关注他 你经常看TA的内容最近看了一些AntDesign的组件源码,学到一些很实用的技巧,这篇文章来分享一下。首先,我们用create-react-app创建个React项目(选择typescript模版):npxcreate-r......