C#自学笔记:多线程
多线程
进程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动是系统进行资源分配和调度的基本单位,是操作系统结构的基础
说人话:打开一个应用程序就是在操作系统上开启了一个进程
- 进程之间可以相互独立运行,互不干扰
- 进程之间也可以相互访问、操作
线程
操作系统能够进行运算调度的最小单位它被包含在进程之中,是进程中的实际运作单位
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程(通过切换时间片实现)
- 我们目前写好的程序都在主线程中
简单理解线程:就是代码从上到下运行的一条“管道”
多线程
我们可以通过代码,开启新的线程可以同时运行代码的多条“管道”就叫多线程
多线程 ≠ 并行:
- 多线程并不等于并行。多线程是指一个程序通过多个线程来执行任务,它可以在单核CPU上通过快速切换模拟并发,或者在多核CPU上实现真正的并行。
- 在单核CPU上,多线程执行任务时,线程实际上是被交替执行的,虽然它们看起来是并行的,但实际上是并发执行的(通过时间分片的方式)。
- 在多核或多处理器的系统中,多线程可以实现真正的并行,即不同线程在不同的CPU核上同时执行,这时候就可以称为并行执行。
语法
线程类 Thread
注意:线程执行的代码需要封装到一个函数中
声明
using System.Threading;
static void Main(string args[])
{
//1. 声明一个线程
Thread t = new Thread(NewThreadLogic);
//2. 启动线程
t.Start();
//3. 设置为后台线程
//当前台线程(主线程?)都结束了的时候,整个程序也就结束了,包括后台程序
//如果不设置为后台线程,当前台线程结束时可能导致进程无法正常关闭
t.IsBackgroud = true;
//4. 关闭释放一个线程
//如果开启的线程不是死循环,执行完会自动关闭
//如果是死循环,想要中止这个线程,有两种方式
//4.1 改变循环条件
//4.2 通过线程提供的方法(注意在.Net core版本中无法中止,会报错)
//好像都说过时了
t.Abort();
t = null;
//5. 线程休眠
//让线程休眠多少毫秒 1s = 1000ms
//在哪个线程里执行,就休眠哪个线程
Thread.Sleep(1000);
}
static void NewThreadLogic()
{
// 新开线程执行的代码逻辑
//当前台线程结束时,即使后台还在运行,也会被结束
while (true)
{
Console.WriteLine("新开线程执行的代码逻辑");
}
}
Threading底层
public sealed class Thread : CriticalFinalizerObject
{
public Thread(ParameterizedThreadStart start);
public Thread(ThreadStart start);
}
public delegate void ThreadStart();
线程之间共享数据
多个线程使用的内存是共享的,都属于该应用程序(进程)所以要注意,当多线程同时操作同一片内存区域时可能会出问题
可以通过加锁的形式避免问题
lock
static object obj = new object();
while(true)
{
lock(obj)
{
//第一条线程代码逻辑
}
}
while(true)
{
lock(obj)
{
//第二条线程代码逻辑
}
}
并行并不意味着就完全没有内存问题。
并行环境下是否会有共享内存问题,取决于任务如何设计和内存的分配方式:
- 共享内存并行:如果多个并行任务(例如多个线程或进程)需要访问相同的内存区域(例如通过共享内存区域、内存映射文件等方式),那么就仍然可能会遇到线程安全问题。这种情况下,多个并行任务之间对共享内存的并发访问依然需要通过同步机制来保护。
- 分布式并行:如果并行任务彼此之间没有共享内存,任务的数据是独立的(例如在不同的核心、不同的机器上运行),那么它们就不会直接出现共享内存访问问题。这种情况下,数据交换一般通过消息传递或文件等手段进行,避免了内存访问冲突。
不同的进程之间会存在线程安全问题吗?
1. 进程之间的内存隔离:
- 每个进程都有自己的独立内存空间,因此一个进程中的线程不能直接访问另一个进程的内存空间。由于内存隔离,进程之间不会出现共享内存的线程安全问题,即一个进程内的线程不会干扰到另一个进程的线程。
- 这也意味着,如果两个进程都有线程在运行,它们不会直接产生竞态条件,因为它们之间没有共享的内存区域。
2. 进程间通信(IPC):
- 虽然进程之间不共享内存,但它们可以通过某些方式进行通信(即进程间通信,IPC),例如:
- 管道(Pipes)
- 共享内存(Shared Memory)
- 消息队列(Message Queues)
- 信号量(Semaphores)
- 套接字(Sockets)
- 如果两个进程通过共享内存来交换数据,那么就需要特别小心并发控制,因为即使是不同进程之间的内存共享,也可能导致并发访问和竞态条件问题。为此,通常需要使用同步机制来保证数据一致性,比如使用互斥锁、信号量等。
3. 进程间的并发问题:
- 虽然进程间本身不发生线程安全问题,但如果两个进程共享某些资源(如文件、数据库等),也可能会出现类似的并发问题。例如:
- 文件锁:多个进程同时访问同一个文件,可能导致数据冲突或文件损坏,因此需要使用文件锁来同步访问。
- 数据库并发:多个进程对同一数据库进行读写操作时,如果没有合适的事务控制,可能会出现数据不一致的问题。
4. 进程与线程安全问题的区别:
- 线程安全问题通常出现在同一进程内的多线程操作中,多个线程共享同一块内存时,如果没有适当的同步控制,就会发生数据竞争和不一致。
- 进程安全问题通常出现在多个进程共享某些外部资源(如共享内存、文件、数据库等)时,进程间需要通过适当的同步机制来避免冲突和不一致。

浙公网安备 33010602011771号