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)
————————————————

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

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

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

相关文章

java如何修改windows计算机本地日期和时间?

本文教程&#xff0c;主要介绍&#xff0c;在java中如何修改windows计算机本地日期和时间。 目录 一、程序代码 二、运行结果 一、程序代码 package com;import java.io.IOException;/**** Roc-xb*/ public class ChangeSystemDate {public static void main(String[] args)…

红队打靶练习:HOLYNIX: V1

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto whatweb 目录探测 1、gobuster 2、dirsearch 3、dirb 4、feroxbuster WEB sqlmap 1、爆库 2、爆表 3、爆列 4、爆字段 后台登录 1、文件上传 2、文件包含 3、越权漏洞 反弹shell 提权 总结 信息…

MATLAB二维与三维绘图实验

本文MATLAB源码&#xff0c;下载后直接打开运行即可[点击跳转下载]-附实验报告https://download.csdn.net/download/Coin_Collecter/88740747 一、实验目的 掌握图形对象属性的基本操作。掌握利用图形对象进行绘图操作的方法。 二、实验内容 利用图形对象绘制曲线&#xff…

【复现】金和 jc6协同管理平台 任意文件上传漏洞(2)_21

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 金和C6协同管理平台包括协同办公管理,人力资源管理,项目管理,客户关系管理,企业目标管理,费用管理,移动办公,微信办公等多个业务范…

智慧校园大数据平台架构

平台架构 基础硬件层 基础硬件层是由一组低廉的PC或服务器组合构建而成。基础硬件层主要承载着数据的存储、运算、容错、调度和通信等任务,对基础应用层下达的指令进行执行和反馈。 数据集成 大数据特征表现在实时、交互、海量等方面,并且以半结构化、非结构化数据为主,价…

操作系统课程设计-Linux 进程间通信

目录 前言 1 实验题目 2 实验目的 3 实验内容 3.1 步骤 3.2 关键代码 3.2.1 Server和Client的创建 3.2.2 Server核心代码 3.2.3 Server核心代码 4 实验结果与分析 5 代码 前言 本实验为课设内容&#xff0c;博客内容为部分报告内容&#xff0c;仅为大家提供参考&…

BuildRoot配置RTL8822CE WIFIBT模块(WIFI部分)

TinkerBoard2主板自带的无线模块为RTL8822CE&#xff0c;PCIe接口 之前在风火轮下载的Linux源码编译出来的BuildRoot根文件系统没有相关的驱动文件 [rootrk3399:/]# find . -name *.ko [rootrk3399:/]# lsmod Module Size Used by Not tainted [rootrk33…

Java--业务场景:在Spring项目启动时加载Java枚举类到Redis中

文章目录 前言实现项目启动时加载枚举值到Redis1. 定义EnumInterface接口2. 创建EnumDTO3. 创建ClassUtils工具类4. 创建EnumService接口5. 创建EnumServiceImpl6. 修改枚举类7. 创建ApplicationInit 测试结果 前言 新的一年即将来到&#xff0c;回首2023年&#xff0c;也是学…

❤ React报错问题分析

❤ React报错问题分析 ❤️ You passed a second argument to root.render(…) but it only accepts one argument. You passed a second argument to root.render(…) but it only accepts one argument. react-dom.development.js:86 Warning: You passed a second argumen…

Redis和MySQL如何保持数据一致性

前言 在高并发的场景下&#xff0c;大量的请求直接访问Mysql很容易造成性能问题。所以&#xff0c;我们都会用Redis来做数据的缓存&#xff0c;削减对数据库的请求。但是&#xff0c;Mysql和Redis是两种不同的数据库&#xff0c;如何保证不同数据库之间数据的一致性就非常关键…

科大讯飞星火大模型接入API js 部分 接口 安装注意事项

下载以下链接例子运行程序 https://xfyun-doc.xfyun.cn/static%2F16968175055332330%2Fspark_js_demo.zip 官网给的说明 准备 1.在demo中填写APPID、APISecret、APIKey&#xff0c;可到控制台-我的应用-大模型页面获取 2.安装nodejs 本地运行 1.打开cmd&#xff0c;进入dem…

CORS漏洞学习

CORS漏洞属于一个协议漏洞&#xff0c;具体是由于同源策略的设置问题触发的漏洞&#xff0c;漏洞利用条件较为苛刻&#xff0c;但实战中也常见。 首先要了解同源策略 什么是同源策略&#xff1f; 同源策略是一种Web浏览器安全机制&#xff0c;旨在防止网站相互攻击。 同源策…