.NET/C#⾯试题汇总系列:多线程

1.根据线程安全的相关知识,分析以下代码,当调⽤test⽅法时i>10时是否会引起死锁?并简 要说明理由。

public void test(int i)
{lock(this){if (i>10){i--;test(i);}}
}

不会发⽣死锁,(但有⼀点int是按值传递的,所以每次改变的都只是⼀个副本,因此不会出现死锁。但如 果把int换做⼀个object,那么死锁会发⽣)

lock 关键字:

用于确保当多个线程同时访问共享资源时,不会发生数据竞争(race condition)或数据不一致的问题。

lock 语句通过获取给定对象的互斥锁来同步代码块,以确保一次只有一个线程可以执行该代码块。

  • 示例 : 线程安全的集合操作
public class ThreadSafeList<T>
{private readonly List<T> _list = new List<T>();private readonly object _lockObject = new object();public void Add(T item){lock (_lockObject){_list.Add(item);}}public void Remove(T item){lock (_lockObject){_list.Remove(item);}}public List<T> GetAll(){lock (_lockObject){return new List<T>(_list);}}
}

在这个例子中,我们创建了一个线程安全的列表类 ThreadSafeList<T>,其中 Add 和 Remove 方法使用 lock 来确保对列表的修改是线程安全的。GetAll 方法也使用 lock 来确保在返回列表的副本时,列表的状态是一致的。

2.描述线程与进程的区别?

  1. 定义与区别‌:

    • 进程‌(Process)是系统进行资源分配和调度的一个独立单元,是操作系统结构的基础。它是应用程序的一次动态执行过程,是程序代码及其数据在运行时的一个实例。它拥有独立的内存空间,包含一组系统资源(如代码、数据和打开的文件等)。
    • 线程‌(Thread)是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的独立运行的单位。一个进程可以拥有多个线程,这些线程共享该进程的所有资源(如内存和打开的文件),但每个线程都拥有自己独立的执行栈和程序计数器。
  2. 资源与开销‌:

    • 进程拥有独立的内存空间和系统资源,因此进程间的通信相对复杂,开销也较大。
    • 线程共享进程的资源,因此线程间的通信相对简单,开销也较小。
  3. 独立性‌:

    • 进程拥有更高的独立性,一个进程的崩溃通常不会影响到其他进程。
    • 线程则不然,一个线程的崩溃可能会导致整个进程的崩溃(取决于线程的异常处理机制)。

3.Windows单个进程所能访问的最⼤内存量是多少?它与系统的最⼤虚拟内存⼀样吗?这对 于系统设计有什么影响?

这个需要针对硬件平台,公式为单个进程能访问的最⼤内存量=2的处理器位数次⽅/2,⽐如通常情况下, 32位处理器下,单个进程所能访问的最⼤内存量为:232 /2 = 2G 。

单个进程能访问的最⼤内存量是最⼤ 虚拟内存的1/2,因为要分配给操作系统⼀半虚拟内存。

4.using() 语法有⽤吗?什么是IDisposable?

有⽤

实现了IDisposiable的类在using中创建,using结束后会⾃定调⽤该对象的Dispose⽅法,释放资 源。

  • using() 语法的用途

using 语句在C#中非常有用,特别是在处理实现了IDisposable接口的对象时。它确保了在代码块执行完毕后,会自动调用对象的Dispose方法,以释放非托管资源(如文件句柄、数据库连接等)。这不仅简化了资源管理,还避免了资源泄露的风险。

  • 什么是IDisposable

IDisposable是.NET中定义的一个接口,它包含一个Dispose方法。当一个类实现了IDisposable接口时,就意味着这个类拥有非托管资源,需要在不再需要时显式释放。Dispose方法通常用于释放这些非托管资源,并可能还包含对托管资源的清理逻辑(如关闭文件流、数据库连接等)。

通过使用using语句,我们可以确保即使发生异常,Dispose方法也会被调用,从而安全地释放资源。

例如:

using (var fileStream = new FileStream("example.txt", FileMode.OpenOrCreate))
{// 使用 fileStream 进行操作
}
// fileStream 的 Dispose 方法会在此处自动调用

FileStream类实现了IDisposable接口,因此我们可以使用using语句来确保fileStream在使用完毕后会被正确关闭和释放资源。

5.前台线程和后台线程有什么区别?

  • 前台线程(Foreground Thread)‌:在.NET中,默认创建的线程都是前台线程。只要应用程序中有任何前台线程在运行,应用程序就会保持运行状态。只有当所有的前台线程都终止时,应用程序才会结束。

  • 后台线程(Background Thread)‌:后台线程不会影响应用程序的终止。一旦所有的前台线程都终止,无论后台线程是否还在运行,应用程序都会自动结束。后台线程通常用于处理那些非关键的、可以异步执行的任务比如数据加载文件操作等。

6.什么是互斥?

当多个线程访问同⼀个全局变量,或者同⼀个资源(⽐如打印机)的时候,需要进⾏线程间的互斥操作来保证 访问的安全性。

7.如何查看和设置线程池的上下限?

  • 线程池的线程数是有限制的,通常情况下,我们⽆需修改默认的配置。但在⼀些场合,我们可能需要了解 线程池的上下限和剩余的线程数。线程池作为⼀个缓冲池,有着其上下限。在通常情况下,当线程池中的 线程数⼩于线程池设置的下限时,线程池会设法创建新的线程,⽽当线程池中的线程数⼤于线程池设置的 上限时,线程池将销毁多余的线程。
  • PS:在.NET Framework 4.0中,每个CPU默认的⼯作者线程数量最⼤值为250个,最⼩值为2个。⽽IO 线程的默认最⼤值为1000个,最⼩值为2个。

在.NET中,通过 ThreadPool 类型提供的5个静态⽅法可以获取和设置线程池的上限和下限,同时它还额 外地提供了⼀个⽅法来让程序员获知当前可⽤的线程数量,

下⾯是这五个⽅法的签名:

① static void GetMaxThreads(out int workerThreads, out int completionPortThreads)

② static void GetMinThreads(out int workerThreads, out int completionPortThreads)

③ static bool SetMaxThreads(int workerThreads, int completionPortThreads)

④ static bool SetMinThreads(int workerThreads, int completionPortThreads)

⑤ static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)

8. Task状态机的实现和⼯作机制是什么?

在.NET中,它会⾃动编译为:

  • 1. 将所有引⽤的局部变量做成 闭包,放到⼀个隐藏的状态机的类中;
  • 2. 将所有的await展开成⼀个状态号,有⼏个await就有⼏个状态 号;
  • 3. 每次执⾏完⼀个状态,都重复回调状态机的MoveNext⽅法,同时指定下⼀个状态号;
  • 4. MoveNext⽅法还需处理线程和异常等问题。

9.await的作⽤和原理,并说明和GetResult()有什么区别?

  • 从状态机的⻆度出发,await的本质是调⽤Task.GetAwaiter()的UnsafeOnCompleted(Action)回调,并 指定下⼀个状态号。
  • 从多线程的⻆度出发,如果await的Task需要在新的线程上执⾏,该状态机的MoveNext()⽅法会⽴即返 回,此时,主线程被释放出来了,然后在UnsafeOnCompleted回调的action指定的线程上下⽂中继续 MoveNext()和下⼀个状态的代码。
  • ⽽相⽐之下,GetResult()就是在当前线程上⽴即等待Task的完成,在Task完成前,当前线程不会释放。 注意:Task也可能不⼀定在新的线程上执⾏,此时⽤GetResult()或者await就只有会不会创建状态机的区 别了。

10.Task和Thread有区别吗?

  1. 抽象层次‌:Task 提供了比 Thread 更高的抽象层次。它代表了异步操作,可以很容易地与C#的异步编程模式(async/await)集成。Thread 则更底层,直接表示操作系统线程。

  2. 资源管理‌:Task 池管理了任务的执行,可以更有效地重用线程,减少线程创建和销毁的开销。相比之下,直接使用 Thread 需要程序员手动管理线程的创建、执行和销毁。

  3. 异步编程支持‌:Task 天然支持C#的异步编程模式,使得编写异步代码更加简单和直观。而 Thread 需要通过额外的机制(如回调函数、轮询等)来实现类似的功能。

11.多线程有什么⽤?

  1. 提高CPU利用率:多线程使得在等待某些任务完成时,如I/O操作或用户输入,CPU可以转而执行其他线程的任务,从而大大提高了CPU的利用率。
  2. 提升系统性能:通过并行处理多个任务,多线程可以显著提高系统的处理能力和性能,尤其是在多核处理器系统中更为明显。
  3. 改善用户体验:在图形用户界面(GUI)应用中,多线程可以实现界面的响应式设计,即使后台正在进行耗时的操作,用户界面也能保持活跃,提升用户体验。
  4. 简化资源共享:同一进程下的所有线程共享进程的资源,如内存空间、文件句柄等,这使得不同任务之间的协调操作与数据交互更加简单高效。
  5. 实现复杂任务:对于需要同时处理多个独立但相关任务的场景,多线程提供了一个有效的解决方案。例如,在服务器端并发处理用户请求时,每个请求可以在一个独立的线程中处理,互不干扰,提高了服务的响应速度和效率。
  6. 优化资源分配:在多线程编程中,可以通过线程同步机制来控制对共享资源的访问,防止数据竞争和死锁的发生,确保系统的稳定性和可靠性。
  7. 增强程序灵活性:多线程技术使得开发者能够更灵活地安排程序的执行流程,通过创建和管理不同的线程,可以有效地应对各种复杂的程序需求。
  8. 支持实时系统:在需要快速响应外部事件的应用中,如实时数据处理或游戏开发,多线程技术可以提供必要的并发执行能力,以满足严格的时间要求。

12. 两个线程交替打印0~100的奇偶数

这道题就是说有两个线程,⼀个名为偶数线程,⼀个名为奇数线程,偶数线程只打印偶数,奇数线程只打 印奇数,两个线程按顺序交替打印。

static AutoResetEvent oddReady = new AutoResetEvent(false);
static AutoResetEvent evenReady = new AutoResetEvent(true);//偶数线程先开始
static void Main(string[] args)
{Thread oddThread = new Thread(PrintOddNumbers);Thread evenThread = new Thread(PrintEvenNumbers);oddThread.Start();evenThread.Start();oddThread.Join();evenThread.Join();Console.WriteLine("打印完成。");
}
static void PrintOddNumbers()
{for (int i = 1; i <= 10; i+=2) { evenReady.WaitOne();// 等待偶数线程完成Console.WriteLine(i);oddReady.Set(); // 通知奇数线程可以运行}
}
static void PrintEvenNumbers()
{for (int i = 0; i <= 100; i += 2){oddReady.WaitOne(); // 等待奇数线程完成Console.WriteLine(i);evenReady.Set(); // 通知偶数线程可以运行}
}

AutoResetEvent 是 C# 中的一个类,用于实现线程同步。它属于 System.Threading 命名空间。

AutoResetEvent 有两种状态:有信号(true)和无信号(false)。

当一个线程调用 WaitOne() 方法时,如果事件处于无信号状态,那么该线程将被阻塞,直到另一个线程调用 Set() 方法将事件设置为有信号状态

一旦事件被设置为有信号状态,WaitOne() 方法将返回,并且事件将自动重置为无信号状态。

13.为什么GUI不⽀持跨线程调⽤?有什么解决⽅法?

因为GUI应⽤程序引⼊了⼀个特殊的线程处理模型,为了保证UI控件的线程安全,这个线程处理模型不允许 其他⼦线程跨线程访问UI元素。

解决⽅法⽐较多的

  • 利⽤UI控件提供的⽅法,Winform是控件的Invoke⽅法,WPF中是控件的Dispatcher.Invoke⽅法;
  • 使⽤BackgroundWorker;
  • 使⽤GUI线程处理模型的同步上下⽂SynchronizationContext来提交UI更新操作

14.说说常⽤的锁,lock是⼀种什么样的锁?

常⽤的如如SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock是⼀个混 合锁,其实质是Monitor

Lock是一种用于控制多个线程对共享资源的访问的同步机制,避免资源竞争和数据不一致的问题。

15.lock为什么要锁定⼀个参数(可否为值类型?)参数有什么要求?

lock关键字用于确保在同一时间只有一个线程可以访问特定的代码块,从而避免资源竞争和数据不一致的问题。

必须是一个引用类型,不能是值类型。这是因为lock的工作机制依赖于对象的内存地址(即引用),而不是对象本身的值。如果使用值类型作为互斥锁,那么每次进入lock语句块时都会创建一个新的值类型对象,这将导致无法正确同步线程。

16.多线程和异步的区别和联系?

  • 多线程‌:指的是程序同时执行多个线程,每个线程可以独立执行不同的任务。多线程主要用于提高程序的执行效率,特别是在多核CPU上,可以并行处理多个任务。
  • 异步编程‌:主要关注的是任务的执行顺序,即不按照代码书写的顺序立即执行,而是当某个操作(如I/O操作)完成时,再执行后续操作。异步编程可以使得在等待操作完成时,程序可以继续执行其他任务,从而提高程序的响应性和吞吐量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/426786.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VirtualBox 克隆已有的虚拟机

【前提】已经存在一个CentOS 7 虚拟机 【需求】克隆出来一个虚拟机,用于本机 【操作】 1.右击已有的虚拟机 -> 选择克隆 2.给新虚拟机起个名称 以及 生成新的MAC地址 3.克隆 4.修改网络和主机名称 # 修改网络编辑以下2个文件 vi /etc/sysconfig/network-scripts/ifcfg-enp…

Java之内部类

目录 实例内部类 静态内部类 局部内部类 匿名内部类 下面将讲解实例内部类&#xff0c;静态内部类&#xff0c;局部内部类和匿名内部类。 实例内部类 实例内部类&#xff08;也称为非静态内部类&#xff09;依赖于外部类的实例。这意味着&#xff0c;要创建实例内部类的实…

Kubernetes从零到精通(12-Ingress、Gateway API)

Ingress和Gateway API都是Kubernetes中用于管理外部访问集群服务的机制&#xff0c;但它们有不同的设计理念和适用场景。它们的基本原理是通过配置规则&#xff0c;将来自外部的网络流量路由到Kubernetes集群内部的服务上。 Ingress/Gateway API和Service Ingress/Gateway API…

Qt窗口——QToolBar

文章目录 工具栏创建工具栏设置toolTip工具栏配合菜单栏工具栏浮动状态 工具栏 QToolBar工具栏是应用程序中集成各种功能实现快捷键使用的一个区域。 可以有多个&#xff0c;也可以没有。 创建工具栏 #include "mainwindow.h" #include "ui_mainwindow.h&qu…

ARM 工业边缘计算机与 C# 编程的完美融合

在工业领域&#xff0c;随着智能化和数字化的不断推进&#xff0c;ARM 工业边缘计算机凭借其出色的性能和低功耗等优势&#xff0c;逐渐成为众多应用场景的重要支撑。而 C# 编程语言的强大功能和广泛适用性&#xff0c;使其在与 ARM 工业边缘计算机的结合中展现出了巨大的潜力。…

壹嘉情,中国与世界经济文化交流的新桥梁

壹嘉情正在全球华商领域迅速崛起。作为意大利华商总会的中国分部&#xff0c;壹嘉情承载着推动两岸及全球华商深度合作、实现资源共享和互利共赢的使命。它的成立标志着意大利华商总会在全球战略布局上的重要一步&#xff0c;同时也昭示了全球化浪潮中&#xff0c;华人企业正加…

LNMP的简单安装(ubuntu)

LNMP介绍 LNMP 是一种常见的开源软件组合&#xff0c;用于搭建高效的网站服务器环境。LNMP 代表以下四个组件&#xff1a; Linux&#xff1a;操作系统。Linux 是一种稳定、可靠、安全的开源操作系统&#xff0c;常用于服务器环境&#xff0c;特别是在企业级部署中。它负责底层…

小程序——生命周期

文章目录 运行机制更新机制生命周期介绍应用级别生命周期页面级别生命周期组件生命周期生命周期两个细节补充说明总结 运行机制 用一张图简要概述一下小程序的运行机制 冷启动与热启动&#xff1a; 小程序启动可以分为两种情况&#xff0c;一种是冷启动&#xff0c;一种是热…

js 深入理解生成器

目录 概述1 . 生成器基础2. 与普通函数的区别3. 通过 yield 中断执行3.1 yield 是干嘛的&#xff1f;3.2 yield 和 return 的区别3.3 每个生成器对象作用域都是独立的3.4 yeild 的使用位置3.5 生成器对象作为可迭代对象3.6 使用 yield 实现输入和输出3.6.1 yield实现输入3.6.1 …

【JVM安装MySQL】

环境 > VMware Workstation Pro > CentOS 7 >Navicat Premium Lite > MobaXterm添加 MySQL Yum 仓库 根据操作系统在下载界面选取对应yum库进行下载 wget https://dev.mysql.com/get/mysql80-community-release-el7-9.noarch.rpm在文件下载界面安装 rpm -ivh mysq…

<<编码>> 第 14 章 反馈与触发器(3)--锁存器与触发器 示例电路

电平触发 D 型触发器 info::操作说明 鼠标单击逻辑输入切换 0|1 状态 因复位和置位不应同时处在高电平, 因此在输入处加入一个非门反向, 然后复位和置位输入合并为 数据(Data) 输入 注: 当保持位为 0 时, 数据输入无效 primary::在线交互操作链接 https://cc.xiaogd.net/?star…

Stylized Smooth Clouds 卡通风格化云朵包

下载:​​Unity资源商店链接资源下载链接 效果图:

Spring考点总结

01.Spring框架的基本理解 关键字:核心思想IOC\AOP\作用(解耦、简化)&#xff0c;简单描述框架组成 Spring框架是一款轻量级的开发框架&#xff0c;核心思想是IOC&#xff08;控制反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;&#xff0c; 为Java应用程序开发…

数字IC设计\FPGA 职位经典笔试面试整理--语法篇 Verilog System Verilog(部分)

注&#xff1a; 资料都是基于网上一些博客分享和自己学习整理而成的 Verilog 1. 数据类型 Verilog一共有19种数据类型 基础四种数据类型&#xff1a;reg型&#xff0c;wire型&#xff0c;integer型&#xff0c;parameter型 reg型   reg类型是寄存器数据类型的关键字。寄存…

软考(中级-软件设计师)(0919)

软考 一、软件设计师-历年考试考点分布情况-上午-计算机与软件工程知识 知识点分数说明比例软件工程基础知识11开发模型、设计原则、测试方法、质量特性、CMM、Pert图、风险管理14.67%面向对象12面向对象基本概念、面向对象分析与设计、UML、常见算法16.00%数据结构与算法10…

【HarmonyOS NEXT】DevEco快速实现真机截屏,并保存到电脑

点日志点照机图标选一个路径保存图片在ide中右键图片&#xff0c;点复制电脑随便找个位置保存图片https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-screenshot-V5

使用Ubuntu耳机输出正弦波信号

最近有一个项目想使用喇叭发出一个标准的正弦波测试信号&#xff0c;故记录下操作过程 sudo apt install libasound2-dev 否则有可能会报错&#xff1a; alsaaudio.c:28:10: fatal error: alsa/asoundlib.h: No such file or directory 安装pyalsaaudio&#xff1a; pip …

IE浏览器彻底去除浏览器缓存的方法

1.浏览器右上方如图操作 2.点击后会弹出窗口&#xff0c;如图操作 3.点击查看文件如图操作 4&#xff0e;点击后会弹出一个文件夹&#xff0c;在文件夹内CtrlA全选删除全部文件就可以&#xff0c;有提示直接确认即可

智能车镜头组入门(三)巡线

镜头组的特点是通过摄像头来获取赛道的信息&#xff0c;从而达到前瞻的效果&#xff0c;完成转向和速度决策。 我们的方案&#xff0c;带上元素识别&#xff0c;大概在TC264上5ms一帧&#xff0c;所以我们开了100hz的图象。 之前我看别的博客上有人说&#xff0c;他们组的50帧…

光伏检测数据集(六种)

光伏检测数据集(六种) 1.并网光伏系统故障诊断数据集 (该数据集为excel张&#xff0c;对故障类型完成标注)。 2.分布式光伏目标检测数据集 (该数据集共4000张分布式光伏高清图片&#xff0c;均已标注) 3.光伏电池板缺陷检测数据集 (该数据集共2400张光伏板缺陷高清图片&#xf…