unity 协程原理与线程的区别

本文探讨了进程、线程及协程的概念及其区别,并通过Unity中的协程执行原理进行了详细说明。文章还通过示例代码展示了协程的运行机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说到协程,我们首先回顾以下线程与进程这两个概念。在操作系统(os)级别,有进程(process)和线程(thread)两个我们看不到但又实际存在的“东西”,这两个东西都是用来模拟“并行”的,写操作系统的程序员通过用一定的策略给不同的进程和线程分配CPU计算资源,来让用户“以为”几个不同的事情在“同时”进行“。在单CPU上,是os代码强制把一个进程或者线程挂起,换成另外一个来计算,所以,实际上是串行的,只是“概念上的并行”。在现在的多核的cpu上,线程可能是“真正并行的”。

1 线程、进程、协程的区别

进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。

线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。

协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力。

打个比方吧,假设有一个操作系统,是单核的,系统上没有其他的程序需要运行,有两个线程 A 和 B ,A 和 B 在单独运行时都需要 10 秒来完成自己的任务,而且任务都是运算操作,A B 之间也没有竞争和共享数据的问题。现在 A B 两个线程并行,操作系统会不停的在 A B 两个线程之间切换,达到一种伪并行的效果,假设切换的频率是每秒一次,切换的成本是 0.1 秒(主要是栈切换),总共需要 20 + 19 * 0.1 = 21.9 秒。如果使用协程的方式,可以先运行协程 A ,A 结束的时候让位给协程 B ,只发生一次切换,总时间是 20 + 1 * 0.1 = 20.1 秒。如果系统是双核的,而且线程是标准线程,那么 A B 两个线程就可以真并行,总时间只需要 10 秒,而协程的方案仍然需要 20.1 秒。 
这里写图片描述

Unity协程执行原理

unity中协程执行过程中,通过yield return XXX,将程序挂起,去执行接下来的内容,注意协程不是线程,在为遇到yield return XXX语句之前,协程额方法和一般的方法是相同的,也就是程序在执行到yield return XXX语句之后,接着才会执行的是 StartCoroutine()方法之后的程序,走的还是单线程模式,仅仅是将yield return XXX语句之后的内容暂时挂起,等到特定的时间才执行。 
那么挂起的程序什么时候才执行,这就要看monoBehavior的生命周期了。 


这里写图片描述
也就是协同程序主要是update()方法之后,lateUpdate()方法之前调用的,接下来我们通过一个小例子去理解一下。

using UnityEngine;
using System.Collections;
using System.Threading;
public class test : MonoBehaviour
{

    void Start()
    {
        StartCoroutine(tt());//开启协程
        for (int i = 0; i < 200; i++)   //循环A
        {
            Debug.Log("*************************" + i);
            Thread.Sleep(10);
        }
    }


    IEnumerator tt()
    {
        for (int i = 0; i < 100; i++) //循环B
        {
            Debug.Log("-------------------" + i);
        }

        yield return new WaitForSeconds(1); //协程1

        for (int i = 0; i < 100; i++) //循环C
        {
            Debug.Log(">>>>>>>>>>>>>>>>>>>>" + i);
            yield return null; //协程1
        }
    }

    // 更新数据
    void Update()
    {
        Debug.Log("Update");
    }

    //晚于更新
    void LateUpdate()
    {
        Debug.Log("------LateUpdate");
    }


}
程序的运行结果为: 
这里写图片描述
先执行循环B,然后执行循环A,然后执行update()和lateUpdate()的方法,等待1S之后,在updat()和lateupda()之间执行循环C的输出。




<think>嗯,用户想了解Unity协程线程区别。首先,我需要回忆一下协程线程的基本概念。协程Unity中通常用于处理异步操作,比如延迟执行或者等待某个条件满足。而线程则是更底层的多任务处理机制,可以并行执行代码。不过Unity的主线程是单线程的,所以线程的使用需要谨慎。 接下来,我应该比较两者的执行方式。协程是在主线程上通过迭代器实现的,它们不会并行执行,而是通过yield语句暂停恢复。线程则是在操作系统级别管理的,可以真正并行运行,但需要处理同步问题。 内存管理方面,协程可能涉及一些堆分配,比如StartCoroutine时会分配一些对象,但yield的时候不会有额外分配。线程需要分配栈空间,每个线程都有自己的栈,这可能消耗更多内存,尤其是在多线程环境下。 适用场景方面,协程适合处理简单的异步任务,比如等待加载资源或动画完成。线程适合计算密集型任务,但要注意不能在子线程中调用Unity的API,因为Unity的大部分组件都不是线程安全的。 然后,我需要参考提供的引用内容。引用[2]提到StartCoroutine会分配CoroutineEnumerator对象,但yield时不会有分配。这支持了协程内存管理的部分。引用[1]讨论了栈堆的区别线程有自己的栈,而堆是共享的,这可能影响线程间数据交互的方式。 用户可能还关心性能影响常见错误。比如,滥用协程可能导致内存泄漏,而线程的同步问题如死锁需要注意。需要提醒用户正确使用协程的停止方法,比如StopCoroutine,以及线程中避免操作Unity对象。 最后,生成相关问题时要覆盖协程线程的具体使用场景、内存管理、性能优化以及常见问题,帮助用户深入理解两者的区别应用。</think>### Unity协程线程区别Unity中,协程(Coroutine)线程(Thread)虽然都用于实现异步操作,但两者在实现原理、内存管理适用场景上存在显著差异。 --- #### **1. 执行方式** - **协程** 协程基于C#的迭代器(`IEnumerator`)实现,通过`yield`语句分段执行代码。协程的代码始终运行在**主线程**上,通过时间分片实现“伪并行”,例如等待资源加载或动画完成。 ```csharp IEnumerator MyCoroutine() { yield return new WaitForSeconds(1); Debug.Log("1秒后执行"); } ``` - **线程** 线程由操作系统直接管理,可以真正实现多核并行计算。但在Unity中,子线程**无法直接操作Unity API**(如`Transform`、`GameObject`),否则会引发错误[^1]。 --- #### **2. 内存分配** - **协程** 启动协程时(通过`StartCoroutine()`),会分配一个`Coroutine`对象(约21字节)一个`Enumerator`对象(约16字节)[^2]。但`yield`语句本身不会产生额外分配。 - **线程** 每个线程默认占用1MB的栈内存(可配置),且频繁创建/销毁线程可能引发GC(垃圾回收)压力。 --- #### **3. 适用场景** | **场景** | 协程 | 线程 | |-----------------------|------|------| | 延迟执行(如等待动画) | ✔️ | ❌ | | 复杂数学计算(如寻路) | ❌ | ✔️ | | 文件/网络IO操作 | ❌ | ✔️ | | Unity对象操作 | ✔️ | ❌ | --- #### **4. 常见问题** 1. **协程泄漏**:未正确停止的协程会持续占用内存,需通过`StopCoroutine()`或禁用脚本终止[^3]。 2. **线程安全**:多线程操作共享数据需使用锁(`lock`)或同步机制,避免竞态条件。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值