基础概念
- 多线程如果给每个线程分配一个CPU这是最优情况,但是线程数量是大于电脑CPU数量的。所以操作系统通过
时间分片
操作模拟并行操作,操作系统通过极快的速度从一个线程切换到另一个线程,并且这个操作叫做上下文切换
。注意上下文切换
存在很大的开销 多线程存在的问题
程序的不确定性
2个线程不断的切换无法确定线程执行顺序内存模型的复杂性
2个线程去访问内存的某个字段,不会去直接访问内存。而是去访问处理器的高速缓冲区
,这个缓冲区定时更新。这个我的理解是A线程修改了字段,但是未同步。B访问了,得到了不同的值。死锁
直接上图
线程API
Task:https://www.cnblogs.com/mq0036/p/9040614.html
#async/await:
await相当于分支;
#Task:
task.Result task函数具有返回值
task 4 种启动方式:
1、run
2、start
3、TaskFactory
4、RunSynchronously 同步执行,阻塞主线程
task控制:
1、task1.Wait()等待某个
2、Task.WaitAll等待所有完成
3、Task.WaitAny等待任何一个
123均为阻塞线程
4、 task1.ContinueWith 一个task执行完执行下一个
5、CancellationTokenSource 调用Cannel取消任务
6、WhenAny、WhenAll和Task.Factory.ContinueWhenAll、Task.Factory.ContinueWhenAny。执行后续操作。不会阻塞
//跑一遍 看对应debug和线程id就明白了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using System.Threading;
public class TestManager : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
AsyncPrintHelloWorld();
}
// Update is called once per frame
void Update()
{
}
public async static void AsyncPrintHelloWorld()
{
Debug.Log("异步方法调用开始");
Debug.Log("开始前id" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1
//这里开启了4个异步方法、并且是在同时执行
var result1 = TMothd1();
var result2 = TMothd2();
var result3 = TMothd3();
var result4 = TMothd4();
Debug.Log("异步方法完成");
int r1 = await result3; //这里先等待时间最长的函数。会发现1、2、3均在在执行并完成,只是这里将主线程给阻塞了,无法继续执行下去,其实已经完成了
Debug.Log("最长耗时任务完成");
int r2 = await result1;
int r3 = await result2;
int r4 = await result4;
Debug.Log("完成所有异步后函数线程id" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1,也在主线程
Debug.Log(r1+"-"+ r2 + "-" + r3 + "-" + r4);
}
/// <summary>
/// 这里测试一下,在这个异步函数中 await 前后的线程情况
/// </summary>
/// <returns></returns>
public async static Task<int> TMothd1()
{
Debug.Log("函数1,await前线程id为:" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1,在主线程
return await Task.Factory.StartNew(() =>
{
Thread.Sleep(5 * 1000); //5秒
Debug.Log("TMothd1 中,当前线程id为" + Thread.CurrentThread.ManagedThreadId);//测试结果id:35
return 1;
});
}
public async static Task<int> TMothd2()
{
return await Task.Factory.StartNew(() =>
{
Thread.Sleep(10 * 1000);//10秒
Debug.Log("TMothd2 完成,当前线程id为" + Thread.CurrentThread.ManagedThreadId);//测试结果id:38
return 2;
});
}
public async static Task<int> TMothd3()
{
return await Task.Factory.StartNew(() =>
{
Thread.Sleep(15 * 1000);//15秒/耗时最长
//Debug.Log("TMothd3 完成");
return 3;
});
}
public async static Task<int> TMothd4()
{
Debug.Log("刚进入函数4线程id为:" + Thread.CurrentThread.ManagedThreadId); // 测试结果id:1,也在主线程
Task<int> task = Task.Factory.StartNew(() =>
{
Thread.Sleep(3 * 1000); //3秒s
Debug.Log("TMothd4 完成,当前线程id为" + Thread.CurrentThread.ManagedThreadId); //在另一个线程
return 3;
});
return await task;
}
}