C# 线程与同步介绍


.NET学习资料

.NET学习资料

.NET学习资料


在 C# 编程中,线程和同步是实现高效、可靠应用程序的关键概念。随着计算机硬件的发展,多核处理器的普及,充分利用多线程技术可以显著提升应用程序的性能和响应速度。而同步机制则是确保多线程环境下数据一致性和程序正确性的重要手段。

一、C# 线程基础

(一)线程的概念与作用

线程是程序执行的最小单元,它是进程内部的一个执行路径。在一个进程中可以包含多个线程,这些线程共享进程的资源,如内存空间、文件句柄等。通过使用多线程,程序可以同时执行多个任务,从而提高系统的利用率和响应性。例如,在一个图形用户界面(GUI)应用程序中,可以使用一个线程来处理用户界面的交互,另一个线程来执行后台数据加载或计算任务,这样可以避免界面卡顿,提升用户体验。

(二)创建和启动线程

在 C# 中,创建线程非常简单,通过System.Threading.Thread类来实现。以下是一个简单的示例:

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // 创建一个新线程,传入线程执行的方法
        Thread thread = new Thread(PrintNumbers);
        // 启动线程
        thread.Start();

        // 主线程继续执行其他任务
        for (int i = 10; i < 20; i++)
        {
            Console.WriteLine($"Main thread: {i}");
        }
    }

    static void PrintNumbers()
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine($"Thread: {i}");
        }
    }
}

在这个示例中,我们创建了一个新线程thread,并将PrintNumbers方法作为线程的执行体。调用thread.Start()方法后,新线程开始执行PrintNumbers方法中的代码,同时主线程继续执行Main方法中的后续代码。

(三)线程的生命周期

线程的生命周期包括以下几个阶段:

新建(New):当使用new关键字创建一个Thread对象时,线程处于新建状态,此时线程还未开始执行。

就绪(Ready):调用Start方法后,线程进入就绪状态,等待 CPU 调度执行。在这个状态下,线程已经具备了执行的条件,但还没有获得 CPU 时间片。

运行(Running):当线程获得 CPU 时间片时,线程进入运行状态,开始执行其关联的方法中的代码。

阻塞(Blocked):在某些情况下,线程可能会进入阻塞状态,例如线程调用了Thread.Sleep方法、等待某个事件发生、获取锁失败等。在阻塞状态下,线程暂时停止执行,直到满足特定的条件后才会重新进入就绪状态。

死亡(Dead):当线程执行完其关联的方法,或者调用了Abort方法终止线程时,线程进入死亡状态,此时线程不再存在。

二、C# 线程同步

(一)线程同步的必要性

在多线程环境下,如果多个线程同时访问和修改共享资源,可能会导致数据不一致和竞态条件(Race Condition)问题。例如,两个线程同时读取一个共享变量的值,然后各自对其进行修改并写回,最终的结果可能取决于线程执行的顺序,这是我们不希望看到的。因此,需要使用线程同步机制来确保在同一时刻只有一个线程能够访问共享资源,从而保证数据的一致性和程序的正确性。

(二)常见的线程同步技术

锁(Lock)

原理:lock关键字用于创建一个互斥锁,它可以确保在同一时刻只有一个线程能够进入被锁定的代码块。当一个线程进入lock代码块时,它会获取锁,其他线程在试图进入该代码块时会被阻塞,直到获取锁的线程退出lock代码块并释放锁。
示例

class SharedResource
{
    private int _count = 0;
    private readonly object _lockObject = new object();

    public void Increment()
    {
        lock (_lockObject)
        {
            _count++;
            Console.WriteLine($"Count: {_count}");
        }
    }
}

class Program
{
    static void Main()
    {
        SharedResource sharedResource = new SharedResource();
        Thread thread1 = new Thread(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                sharedResource.Increment();
            }
        });
        Thread thread2 = new Thread(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                sharedResource.Increment();
            }
        });

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();
    }
}

在这个示例中,SharedResource类中的Increment方法使用lock关键字来保护对_count变量的访问,确保在多线程环境下_count的修改是安全的。

Monitor 类

原理:Monitor类提供了更底层的线程同步控制,它包含了Enter、Exit、Wait、Pulse和PulseAll等方法。Enter方法用于获取对象的锁,Exit方法用于释放锁,Wait方法用于使当前线程等待,直到其他线程调用Pulse或PulseAll方法通知它,Pulse方法用于通知等待队列中的一个线程,PulseAll方法用于通知等待队列中的所有线程。
示例

class MonitorExample
{
    private static readonly object _lockObject = new object();
    private static bool _isReady = false;

    public static void ThreadA()
    {
        Monitor.Enter(_lockObject);
        try
        {
            while (!_isReady)
            {
                Monitor.Wait(_lockObject);
            }
            Console.WriteLine("ThreadA is running");
        }
        finally
        {
            Monitor.Exit(_lockObject);
        }
    }

    public static void ThreadB()
    {
        Monitor.Enter(_lockObject);
        try
        {
            _isReady = true;
            Monitor.Pulse(_lockObject);
            Console.WriteLine("ThreadB signaled ThreadA");
        }
        finally
        {
            Monitor.Exit(_lockObject);
        }
    }
}

在这个示例中,ThreadA线程在_isReady为false时调用Monitor.Wait方法进入等待状态,ThreadB线程将_isReady设置为true后调用Monitor.Pulse方法通知ThreadA线程,ThreadA线程收到通知后继续执行。

Mutex(互斥量)

原理:Mutex(互斥量)与lock类似,但它可以跨进程使用,用于同步不同进程之间的资源访问。Mutex可以确保在同一时刻只有一个线程或进程能够获取到互斥量,从而访问共享资源。
示例

using System.Threading;

class MutexExample
{
    private static readonly Mutex _mutex = new Mutex(false, "MyMutex");

    public static void AccessResource()
    {
        _mutex.WaitOne();
        try
        {
            Console.WriteLine("Thread has acquired the mutex and is accessing the resource");
            // 模拟资源访问操作
            Thread.Sleep(1000);
        }
        finally
        {
            _mutex.ReleaseMutex();
            Console.WriteLine("Thread has released the mutex");
        }
    }
}

在这个示例中,MutexExample类中的AccessResource方法使用Mutex来保护对共享资源的访问,WaitOne方法用于获取互斥量,ReleaseMutex方法用于释放互斥量。

Semaphore(信号量)

原理:Semaphore(信号量)用于控制同时访问某个资源的线程数量。它维护一个许可计数,线程在访问资源前需要获取一个许可,如果许可计数为零,线程将被阻塞,直到有其他线程释放许可。
示例

using System.Threading;

class SemaphoreExample
{
    private static readonly Semaphore _semaphore = new Semaphore(3, 3);

    public static void AccessResource()
    {
        _semaphore.WaitOne();
        try
        {
            Console.WriteLine("Thread has acquired a semaphore permit and is accessing the resource");
            // 模拟资源访问操作
            Thread.Sleep(1000);
        }
        finally
        {
            _semaphore.Release();
            Console.WriteLine("Thread has released the semaphore permit");
        }
    }
}

在这个示例中,SemaphoreExample类中的AccessResource方法使用Semaphore来限制同时访问资源的线程数量为 3,WaitOne方法用于获取许可,Release方法用于释放许可。

三、线程同步的应用场景

多线程访问共享数据:在多个线程需要访问和修改共享数据时,如数据库连接、共享内存区域等,必须使用线程同步机制来确保数据的一致性和完整性。

生产者 - 消费者模型:在生产者 - 消费者模型中,生产者线程生成数据并放入共享缓冲区,消费者线程从缓冲区中取出数据进行处理。为了避免缓冲区溢出和数据竞争,需要使用线程同步机制来协调生产者和消费者的操作。

资源池管理:例如数据库连接池、线程池等资源池的管理,需要使用线程同步来确保资源的正确分配和回收,避免资源的过度使用和浪费。

通过以上对 C# 线程与同步的介绍,希望能帮助你深入理解这两个重要概念及其在实际开发中的应用。如果你对代码实现细节、原理有进一步的疑问,或者想要了解更多相关应用场景,欢迎随时交流。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[ESP32:Vscode+PlatformIO]添加第三方库 开源库 与Arduino导入第三方库的区别

前言 PlatformIO与Arduino在添加第三方库方面的原理存在显著差异 在PlatformIO中&#xff0c;第三方库的使用是基于项目&#xff08;工程&#xff09;的。具体而言&#xff0c;只有当你为一个特定的项目添加了某个第三方库后&#xff0c;该项目才能使用该库。这些第三方库的文…

了解AI绘图,Stable Diffusion的使用

AI绘图对GPU算力要求较高。 个人电脑配置可参考&#xff1a; CPU&#xff1a;14600kf 盒装 显卡&#xff1a;RTX 4080金属大师 OC&#xff0c;16G显存 主板&#xff1a;z790吹雪d4 内存&#xff1a;芝奇皇家戟4000c18,162G 硬盘&#xff1a;宏基gm7000 1T 散热&#xff1a;追风…

linux环境自动化golang项目启动脚本解析

一.场景介绍 当在本地创建了golang项目,修改了代码功能,怎么在远程测试服务器上更新该功能呢,可以使用下面的步骤来解决该问题(这只是其中一种方法): (1).推送最新代码到远程仓库 (2).在测试服务器上创建该项目并拉取最新代码 (3).创建deploy.sh脚本 (4).运行deploy.sh脚本 二.…

归一化与伪彩:LabVIEW图像处理的区别

在LabVIEW的图像处理领域&#xff0c;归一化&#xff08;Normalization&#xff09;和伪彩&#xff08;Pseudo-coloring&#xff09;是两个不同的概念&#xff0c;虽然它们都涉及图像像素值的调整&#xff0c;但目的和实现方式截然不同。归一化用于调整像素值的范围&#xff0c…

基于DeepSeek API和VSCode的自动化网页生成流程

1.创建API key 访问官网DeepSeek &#xff0c;点击API开放平台。 在开放平台界面左侧点击API keys&#xff0c;进入API keys管理界面&#xff0c;点击创建API key按钮创建API key&#xff0c;名称自定义。 2.下载并安装配置编辑器VSCode 官网Visual Studio Code - Code Editing…

Open WebUI项目源码学习记录(从0开始基于纯CPU环境部署一个网页Chat服务)

感谢您点开这篇文章:D&#xff0c;鼠鼠我是一个代码小白&#xff0c;下文是学习开源项目Open WebUI过程中的一点笔记记录&#xff0c;希望能帮助到你&#xff5e; 本人菜鸟&#xff0c;持续成长&#xff0c;能力不足有疏漏的地方欢迎一起探讨指正&#xff0c;比心心&#xff5e…

SSM仓库物品管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.用户登录代码&#xff1a;2.保存物品信息代码&#xff1a;3.删除仓库信息代码&#xff1a; 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SSM框架开发的仓库…

Python微博动态爬虫

本文是刘金路的《语言数据获取与分析基础》第十章的扩展&#xff0c;详细解释了如何利用Python进行微博爬虫&#xff0c;爬虫内容包括微博指定帖子的一级评论、评论时间、用户名、id、地区、点赞数。 整个过程十分明了&#xff0c;就是用户利用代码模拟Ajax请求&#xff0c;发…

时序数据库:Influxdb详解

文章目录 一、简介1、简介2、官网 二、部署1、安装2、配置&#xff08;1&#xff09;用户初始化 三、入门&#xff08;Web UI&#xff09;1、加载数据&#xff08;1&#xff09;上传数据文件&#xff08;2&#xff09;代码接入模板 2、管理存储桶&#xff08;1&#xff09;创建…

unity学习32:角色相关1,基础移动控制

目录 0 应用商店 1 角色上新增CharacterController 组件 1.1 角色上新增CharacterController 组件 1.2 如果没有这个则会报错 2 速度 2.1 默认速度&#xff0c;按帧率计算 2.2 修改速度为按时间计算 2.3 movespeed&#xff0c;基础是1米/秒&#xff0c;这个就是每 move…

Centos Ollama + Deepseek-r1+Chatbox运行环境搭建

Centos Ollama Deepseek-r1Chatbox运行环境搭建 内容介绍下载ollama在Ollama运行DeepSeek-r1模型使用chatbox连接ollama api 内容介绍 你好&#xff01; 这篇文章简单讲述一下如何在linux环境搭建 Ollama Deepseek-r1。并在本地安装的Chatbox中进行远程调用 下载ollama 登…

mysql8.0使用pxc实现高可用

环境准备 准备三台虚拟机&#xff0c;其对应的主机名和IP地址为 pxc-1192.168.190.129pxc-2192.168.190.133pxc-3192.168.190.134 解析,都要做解析 测试 下载pxc的安装包&#xff0c; 官网&#xff1a;https://www.percona.com/downloads 选择8.0的版本并下载&#xff0c;…

LabVIEW污水生化处理在线监测

污水处理是环保领域的重要工作&#xff0c;传统污水处理方法在监测方面存在实时性差、操作不便等问题。为解决这些问题&#xff0c;本项目设计并实现了一套基于LabVIEW的污水生化处理在线监测平台&#xff0c;能够实时监测污水处理过程中的关键参数&#xff0c;如温度、pH值、溶…

【AI学习】关于 DeepSeek-R1的几个流程图

遇见关于DeepSeek-R1的几个流程图&#xff0c;清晰易懂形象直观&#xff0c;记录于此。 流程图一 来自文章《Understanding Reasoning LLMs》&#xff0c; 文章链接&#xff1a;https://magazine.sebastianraschka.com/p/understanding-reasoning-llms?continueFlagaf07b1a0…

vs封装dll 给C#使用

一&#xff0c;vs创建控制台应用 创建控制台应用得好处时&#xff0c;我们可以自己测试接口&#xff0c;如果接口没有问题&#xff0c;改成dll重新编译一遍就可以。 二&#xff0c; 创建一个c 类&#xff0c;将所需提供得功能 封装到类中。 这样可以将 所有功能&#xff0c;进…

ubuntu20使用tigervnc远程桌面配置记录

一、安装tigervnc sudo apt install tigervnc-common sudo apt install tigervnc-standalone-server二、增加配置文件 安装完后新增配置文件&#xff1a;vim ~/.vnc/xstartup #!/bin/sh #Uncomment the following two lines for normal desktop: #unset SESSION_MANAGER #ex…

DeepSeek使用技巧大全(含本地部署教程)

在人工智能技术日新月异的今天&#xff0c;DeepSeek 作为一款极具创新性和实用性的 AI&#xff0c;在众多同类产品中崭露头角&#xff0c;凭借其卓越的性能和丰富的功能&#xff0c;吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能&#xff0c;它基于先进…

网络原理之HTTPS(如果想知道网络原理中有关HTTPS的知识,那么只看这一篇就足够了!)

前言&#xff1a;随着互联网安全问题日益严重&#xff0c;HTTPS已成为保障数据传输安全的标准协议&#xff0c;通过加密技术和身份验证&#xff0c;HTTPS有效防止数据窃取、篡改和中间人攻击&#xff0c;确保通信双方的安全和信任。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要…

MySQL 8.0.41 终端修改root密码

1.在 MySQL 命令行中&#xff0c;运行以下命令修改密码 ALTER USER rootlocalhost IDENTIFIED BY new_password; 其中&#xff0c;new_password替换为你想要设置的新密码 2.退出 MySQL终端&#xff0c;重新打开&#xff0c;使用新密码进入&#xff0c;修改成功

TCP服务器与客户端搭建

一、思维导图 二、给代码添加链表 【server.c】 #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <fcntl.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.…