C# 线程学习:线程的创建、暂停、锁(lock、Monitor)及使用注意事项(一)
八股文
在多线程编程中,线程的创建、暂停、锁机制是非常重要的概念。本文将介绍如何在 C# 中创建线程、暂停线程、使用 lock 和 Monitor 进行线程同步,并分享一些线程使用中的注意事项。
线程与进程
- 进程:程序的一次执行过程,拥有独立的内存空间。
- 线程:进程中的一条执行路径,多个线程共享进程的内存空间。一个进程至少有一个线程,称为主线程。
在 C# 中,线程不支持直接获取返回值。如果需要返回值,可以使用 Task。
Foreground 线程与 Background 线程
- Foreground 线程:默认类型,只要有一个 Foreground 线程在运行,应用程序就不会关闭。
- Background 线程:应用程序退出时,Background 线程会立即终止。可以通过
IsBackground属性设置线程类型。
注意事项
- 异常捕获:异常捕获代码应写在线程内部,而不是线程调用的位置。
- 共享变量:多个线程共享全局变量时,一个线程对变量的修改会影响其他线程。
代码示例
1. 线程的创建
C# 提供了多种创建线程的方式,以下是几种常见的创建线程的方法:
using System;
using System.Threading;
namespace CSharpThreadLearning
{
internal class Program
{
static void Main(string[] args)
{
// 无参数线程
Console.WriteLine("无参数线程创建:");
CreateThreadWithoutParameter();
// 有参数线程
Console.WriteLine("\n有参数线程创建:");
CreateThreadWithParameter("今天是2023年");
// 使用 Lambda 表达式创建线程
Console.WriteLine("\n使用 Lambda 表达式创建线程:");
CreateThreadWithLambda();
Console.ReadLine();
}
/// <summary>
/// 创建无参数线程
/// </summary>
private static void CreateThreadWithoutParameter()
{
Thread thread = new Thread(ThreadProc);
thread.Start();
}
/// <summary>
/// 创建有参数线程
/// </summary>
private static void CreateThreadWithParameter(object parameter)
{
Thread thread = new Thread(ThreadProcWithParameter);
thread.Start(parameter);
}
/// <summary>
/// 使用 Lambda 表达式创建线程
/// </summary>
private static void CreateThreadWithLambda()
{
Thread thread = new Thread(() => Console.WriteLine("Hello from Lambda!"));
thread.Start();
}
/// <summary>
/// 无参数线程执行的方法
/// </summary>
private static void ThreadProc()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("你好,我的朋友");
Thread.Sleep(100);
}
}
/// <summary>
/// 有参数线程执行的方法
/// </summary>
private static void ThreadProcWithParameter(object parameter)
{
Console.WriteLine("传递的参数是: " + (string)parameter);
}
}
}
2. 线程间的变量共享
多个线程可以共享全局变量。以下示例展示了两个线程共享一个全局变量的情况:
public static int number = 0;
private static void Func1()
{
for (; number < 10; number++)
{
Console.WriteLine($"当前是线程1,number={number}");
Thread.Sleep(100);
}
}
private static void Func2()
{
for (; number < 10; number++)
{
Console.WriteLine($"当前是线程2,number={number}");
Thread.Sleep(100);
}
}
3. 使用 lock 进行线程同步
lock 关键字用于确保同一时间只有一个线程访问共享资源,避免竞争条件。
private static object lockToken = new object();
private static void ThreadLine1()
{
lock (lockToken)
{
for (; number < 10; number++)
{
Console.WriteLine($"当前是线程1,number={number}");
Thread.Sleep(100);
}
}
}
private static void ThreadLine2()
{
lock (lockToken)
{
for (; number < 15; number++)
{
Console.WriteLine($"当前是线程2,number={number}");
Thread.Sleep(100);
}
}
}
4. 使用 Monitor 进行线程同步
Monitor 提供了比 lock 更灵活的线程同步机制。
private static void ThreadLine4()
{
Monitor.Enter(lockToken);
try
{
for (; number < 10; number++)
{
Console.WriteLine($"当前是线程1,number={number}");
Thread.Sleep(100);
}
}
finally
{
Monitor.Exit(lockToken);
}
}
private static void ThreadLine5()
{
Monitor.Enter(lockToken);
try
{
for (; number < 15; number++)
{
Console.WriteLine($"当前是线程2,number={number}");
Thread.Sleep(100);
}
}
finally
{
Monitor.Exit(lockToken);
}
}
及使用注意事项(一)&spm=1001.2101.3001.5002&articleId=146380840&d=1&t=3&u=e334a918cb2f42a6a40fe9cd5d8c024d)
4260

被折叠的 条评论
为什么被折叠?



