unity C#什么是线程锁,以及使用案例

文章目录

    • 原理
      • 1. **互斥**(Mutual Exclusion):
      • 2. **缓存一致性与内存屏障**:
      • 3. **操作系统的支持**:
      • 4. **编程语言级别的实现**:
      • 5. **避免死锁**:
      • 图示
    • 实例1
    • 实例2

原理

线程锁的原理主要是为了在多线程环境下提供对共享资源访问的同步机制,防止多个线程同时读写同一数据导致的数据不一致、竞态条件和死锁等问题。以下是线程锁基本工作原理的概述:

1. 互斥(Mutual Exclusion):

线程锁的核心原理是互斥,即在同一时刻,只有一个线程能够获得锁并执行临界区(Critical Section)内的代码。当一个线程进入临界区时,它会先获取锁,此时其他试图获取该锁的线程将被阻塞或挂起,直到持有锁的线程执行完临界区内的代码,并释放锁。

2. 缓存一致性与内存屏障

在现代CPU架构中,为了提高性能,每个处理器都有自己的高速缓存,这就可能导致不同线程看到的数据不一致。线程锁在硬件层面通常配合内存屏障(Memory Barrier)使用,确保缓存中的数据在锁的获取和释放时与主内存保持一致,即修改后的数据会被及时刷新到主内存,而其他线程在获取锁后能从主内存重新加载最新的数据。

3. 操作系统的支持

在操作系统层面,比如Linux系统中,通过pthread_mutex_t这样的互斥量来实现线程锁。操作系统内核提供了原子操作来管理这些互斥量的状态,使得加锁、解锁的过程对于所有参与竞争的线程都是可见且有序的。

4. 编程语言级别的实现

在C#等高级编程语言中,可以通过关键字如lock(C#)或者synchronized(Java)来简化线程锁的使用。例如,在C#中,lock (obj)语句会隐式地调用Monitor类的Enter和Exit方法,从而实现对指定对象的加锁和解锁操作。

5. 避免死锁

为了避免死锁的发生,线程锁的使用需要遵循一定的规则,如避免循环等待锁的情况,以及在持有锁的情况下尽量不要尝试获取其他锁(除非满足特定的锁顺序)。

总结起来,线程锁通过强制单一线程在某一时刻独占资源,以及协调各个线程之间的执行顺序,来达到多线程环境下的资源共享安全和数据一致性。

图示

在这里插入图片描述

在Unity中,线程锁(Thread Lock)是一种同步机制,用于保护多线程环境下的共享资源不被多个线程同时访问和修改。由于Unity引擎本身主要运行在一个单线程(即主线程)上,但现代Unity项目中经常使用多线程处理耗时操作,如网络通信、文件I/O、计算密集型任务等,这时线程锁就显得尤为重要。

Unity中的线程锁通常采用C#的标准库System.Threading命名空间下的Mutex、Monitor或Semaphore类来实现,最常用的是Monitor类以及其提供的Enter和Exit方法,或者更简洁的lock关键字。

实例1

例如,假设我们有一个在多线程环境中需要安全访问和修改的共享数据结构:

public class ThreadSafeExample : MonoBehaviour
{
    // 共享资源
    private Queue<string> messageQueue = new Queue<string>();
    private object queueLock = new object(); // 创建一个对象作为锁

    // 线程A:添加消息到队列
    private void EnqueueMessage(string msg)
    {
        lock (queueLock) // 使用lock语句进行加锁
        {
            messageQueue.Enqueue(msg);
            Debug.Log("Enqueued message: " + msg);
        }
    }

    // 线程B:从队列中取出并处理消息
    private void ProcessNextMessage()
    {
        string msg;
        lock (queueLock) // 同样在此区域加锁
        {
            if (messageQueue.Count > 0)
            {
                msg = messageQueue.Dequeue();
            }
            else
            {
                msg = null;
            }
        }

        if (msg != null)
        {
            Debug.Log("Processing message: " + msg);
            // 这里处理消息...
        }
    }

    // 启动线程
    private void StartThreads()
    {
        Thread sendThread = new Thread(EnqueueMessages);
        Thread receiveThread = new Thread(ProcessMessages);

        sendThread.Start();
        receiveThread.Start();
    }
}

在这个例子中,queueLock对象作为线程锁来确保当一个线程正在向队列中添加消息时,另一个线程不会同时尝试从队列中移除消息。通过使用lock关键字,我们可以创建一段互斥代码块,同一时刻只有一个线程能够执行这段代码,从而避免了竞态条件和其他并发问题。

实例2

当然,线程锁的使用场景非常广泛,下面是一个Unity中使用线程进行异步加载资源,并利用线程锁确保资源安全加载和访问的例子:

using UnityEngine;
using System.Collections;
using System.Threading;
using System.Collections.Generic;

public class ThreadSafeResourceLoader : MonoBehaviour
{
    private readonly object resourceLock = new object();
    private Dictionary<string, Texture2D> loadedTextures = new Dictionary<string, Texture2D>();

    public void LoadTextureAsync(string texturePath)
    {
        var thread = new Thread(() =>
        {
            Texture2D texture = null;
            
            // 异步加载资源
            WWW www = new WWW("file://" + texturePath);
            while (!www.isDone) { /* 等待加载完成 */ }

            if (string.IsNullOrEmpty(www.error))
            {
                texture = www.texture;
            }
            else
            {
                Debug.LogError("Failed to load texture: " + www.error);
            }

            // 使用线程锁安全地将加载好的资源添加到字典
            lock (resourceLock)
            {
                loadedTextures[texturePath] = texture;
            }
        });

        thread.Start();
    }

    public Texture2D GetLoadedTexture(string texturePath)
    {
        Texture2D texture = null;

        // 使用线程锁安全地从字典中获取已加载的资源
        lock (resourceLock)
        {
            loadedTextures.TryGetValue(texturePath, out texture);
        }

        return texture;
    }
}

在这个例子中,LoadTextureAsync方法在新线程中异步加载纹理资源,加载完成后通过线程锁resourceLock安全地将加载好的纹理添加到loadedTextures字典中。同时,在主线程或其他线程调用GetLoadedTexture方法时,同样需要通过线程锁确保在读取已加载纹理时不会发生竞态条件。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

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

相关文章

FastAdmin西陆教育系统(xiluEdu)开源代码

应用介绍 一款基于FastAdminThinkPHPUniapp开发的西陆教育系统&#xff08;微信小程序、移动端H5、安卓APP、IOS-APP&#xff09;&#xff0c;以下是教育系统所包含的一些功能&#xff1a; 视频课程&#xff1a;教育系统提供在线视频课程&#xff0c;学生可以通过网络观看教师…

双双入选 中科驭数第二代DPU芯片K2和低时延DPU卡荣获2023年北京市新技术新产品新服务认定

北京市新技术新产品&#xff08;服务&#xff09;认定是北京市从重点发展的先导技术、战略性新兴产业和现代服务业领域中&#xff0c;选拔出技术先进、产权明晰、质量可靠、市场前景广阔&#xff0c;且符合构建“高精尖”经济结构要求的产品及服务&#xff0c;具有较高权威性和…

C盘满了,我用什么思路清理?

20240115 上周六同事传了一个很大的虚拟机给我&#xff0c;C盘就红了 虽然是飞秋选错了存储文件的路径&#xff0c;但后来忘了&#xff0c;就开始毫无目的删除文件&#xff0c;过程中会有没有权限删除的&#xff0c;这样还是没有改善。 咨询了公司IT技术人员&#xff0c; 告…

conda环境下No module named ‘pytorch_lightning‘问题解决

1 问题描述 在训练wav2lip模型时&#xff0c;出现如下错误&#xff1a; D:\.conda\wav2lip\python.exe D:/ml/wav2lip384/parallel_syncnet_tanh.py --data_root D:/ml/Wav2Lip/data/25fps_out/ --checkpoint_dir syncnet_checkpoints/ --checkpoint_path Traceback (most re…

Java学习(十七)--IO流

File类 介绍 文件是保存数据的地方&#xff0c;而文件在程序中是以流的形式来操作&#xff1b; java.io.File类是 java.io 包中唯一代表磁盘文件本身的对象&#xff1b; 如果希望在程序中操作文件和目录&#xff0c;则都可以通过 File 类来完成 file能新建、删除、重命名…

2、HarmonyOS系统架构

一、HarmonyOS系统采用分层架构 1、整体系统功能按照&#xff1a; “系统>子系统>功能/模块”逐级展开。 在多设备部署场景下&#xff0c;支持根据实际需求裁剪某些非必要的子系统或功能/模块。 2、内核子系统&#xff1a; HarmonyOS采用多内核设计&#xff0c;支持针…

鸿蒙系统ArkTs语法入门

鸿蒙系统ArkTs的ts语法入门 前言1. 变量声明2. 数据类型2.1 基本数据类型2.2 复杂数据类型2.3 联合类型2.4 空类型和未定义类型 3. 函数3.1 匿名函数和箭头函数 4. 类和接口类的访问权限接口类的继承内部类 7. 结构体参考材料 前言 每个语言都有控制流语句就不写测试代码了。 …

用通俗易懂的方式讲解:使用 LangChain 和 LlamaIndex 从零构建PDF聊天机器人

随着大型语言模型&#xff08;LLM&#xff09;&#xff08;如ChatGPT和GPT-4&#xff09;的兴起&#xff0c;现在比以往任何时候都更容易搭建智能聊天机器人&#xff0c;并且可以堆积如山的文档&#xff0c;为你的输入提供更准确的响应。 无论你是想构建个人助理、定制聊天机器…

手把手教你学会接口自动化系列十三-将所有的crm用例由json改为excel

本篇汇总我写接口自动化用到的所有excel数据如下&#xff1a; 登录模块 添加线索模块 添加场景模块

Java调用openai微调Fine-tuning实战示例

注: 建议先看微调文档, 遵从官网给出的规则。例如: jsonl训练文件至少有10个例子, 否则报错 官网微调文档https://platform.openai.com/docs/guides/fine-tuning官网微调APIhttps://platform.openai.com/docs/api-reference/fine-tuning 1. 实现步骤 1. 准备好jsonl数据集2…

three.js设置模型边界线

three.js设置模型边界线 图例 步骤 拿到模型&#xff08;如果是外部模型需要遍历&#xff09;&#xff0c;设置透明度根据模型的几何体创建EdgesGeometry几何体创建线条材质创建LineSegments线模型模型加入线模型 代码 const m model.scene.getObjectByName("仓库&qu…

第 3 章 稀疏数组和队列

文章目录 3.1 稀疏 sparsearray 数组3.1.1 先看一个实际的需求3.1.2 基本介绍3.1.3 应用实例3.1.4 课后练习 3.2 队列3.2.1 队列的一个使用场景3.2.2 队列介绍3.2.3 数组模拟队列思路3.2.4 数组模拟环形队列 3.1 稀疏 sparsearray 数组 3.1.1 先看一个实际的需求  编写的五…

众和策略:券商又念“紧箍咒” 绕标套现的头疼了

又有券商对两融事务念“紧箍咒”。 近来&#xff0c;记者从广发证券获悉&#xff0c;该公司已发布《关于调整融资融券负债归还规矩的告诉》&#xff0c;自2024年1月15日起&#xff0c;决议禁止融资买入证券用于归还融券负债。 相关业内人士以为&#xff0c;自上一年10月融资融…

【数据结构 】哈夫曼编译码器

数据结构-----哈夫曼编译码器 题目题目描述基本要求算法分析 代码实现初始化编码解码打印代码打印哈夫曼树 总结 题目 题目描述 利用哈夫曼编码进行信息通信可大大提高信道利用率&#xff0c;缩短信息传输时间&#xff0c;降低传输成本。 要求&#xff1a;在发送端通过一个编…

DC电源模块与AC电源模块的对比分析

DC电源模块与AC电源模块的对比分析 BOSHIDA DC电源模块和AC电源模块是两种常见的电源模块&#xff0c;它们在供电方式、稳定性、适用范围等方面有所不同&#xff0c;下面是它们的对比分析&#xff1a; 1. 供电方式&#xff1a; DC电源模块通过直流电源供电&#xff0c;通常使用…

韩国Neowine(纽文微)第三代加密芯片ALPU-C

由工采网代理的ALPU-C是韩国Neowine&#xff08;纽文微&#xff09;推出第三代加密芯片&#xff1b;是ALPU系列中的高端IC&#xff1b;其加密性更强、低耗电、体积小&#xff1b;使得防复制、防抄袭板子的加密性能大大提升&#xff0c;让系统产品及嵌入式软体的开发商更能有效保…

C#,字符串匹配(模式搜索)原生(Native)算法的源代码

算法没什么可说的&#xff0c;就是一段一段匹配呗。 运行效果&#xff1a; 源代码&#xff1a; using System; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { /// <summary> /// 字符串匹配&#xf…

虹科分享 | PCAN工具:强大的CAN通讯解决方案,你了解多少?

导读&#xff1a;在当今的汽车和工业自动化领域&#xff0c;可靠的通讯系统至关重要&#xff0c;PCAN工具为这些应用提供了强大的支持。本文将介绍PCAN工具的功能、应用和优势&#xff0c;以帮助您根据实际需求选择合适的工具和配件。 PCAN 网络允许 PCAN 应用程序&#xff08…

JVM:从零到入门

JVM&#xff0c;就是Java虚拟机。 JVM是一个巨大的话题&#xff0c;我们本文主要简单介绍一些围绕JVM相关的基础知识。 目录 JVM内存区域划分 本地方法栈 虚拟机栈 堆 程序计数器 方法区/ 元数据区 类加载 1.加载 2.验证 3.准备 4.解析 5.初始化 双亲委派模型 …