[多线程] Thread
多线程
概述
单任务处理:一个任务完成后才能进行下一个任务。
多任务处理:cpu分时操作,每个任务看似同时运行。
进程
应用程序的一个运行实例,包含程序所需资源的内存区域,是操作系统进行资源分配的单元,进程隔离了正在执行的不同程序。(打开某一个软件,分配cpu,隔离其他软件)
优点:进程间相互独立,互不影响。
线程
进程中的一个执行单元(进程是程序边界,要靠线程执行程序,线程指向方法,执行完毕释放线程),是cpu分配时间片的单位,一个进程可以包含多个线程,且相互独立,共享当前进程所有资源。
优点:
- 并发执行,合理使用cpu资源。
- 相同程序的线程共享堆内存。
缺点:
- 频繁创建/销毁线程增加性能开销。
- 访问共享资源可能造成冲突。
- 辅助线程不能访问unity api。
注意事项:
- unity的api不能在辅助线程运行。
- unity定义的基本结构(int,vector3,quaternion等)可以在辅助线程计算。
- unity定义的基本类型的函数可以在分线程运行。
多线程
在单核系统的一个单位时间内,cpu只能运行单个线程,运行顺序取决于线程的优先级。如果在单位时间内线程未能完成执行,系统就会把线程的状态信息保存到线程的本地存储器(tls) 中,以便下次执行时恢复执行。因为切换频密,所以多线程可被视作同时运行,而实际只是一个假象。
在多核系统的一个单位时间内,进程或线程可以在不同的cpu中运行,使得真正的并行处理。
适用性
耗时的任务,通过多线程可以并行处理。
一个程序完成多个任务,通过多个线程使用多核cpu来处理,可以提升性能。
多线程实现
命名空间:system.threading;
using system.collections; using system.collections.generic; using unityengine; using system.threading; public class threaddemo1 : monobehaviour { private thread thread; private void start01() { //func1();//同步调用 一次性完成0 1 2 3 4 .... //线程调用 //thread = new thread(fun1); //thread.start(); //睡眠一秒 期间没有cpu调度 0 睡眠一秒,依次循环 1 2 3 4... //thread = new thread(fun2); //thread.start(5); //方法重载 参数object类型 thread = new thread(fun4); thread.start(); //threadpool.queueuserworkitem(fun3,null); //线程池开辟的线程无法设置前后台/优先级等 //通过线程池开辟线程 不能start启用 } //thread.start() //无参 private void fun1() { for (int i = 0; i < 30; i++) { signal.waitone(3000); //整数 代表最长的等待时间 thread.sleep(1000); print(i); } } ////thread.start(5) //有参 private void fun2(object o) { int count = (int)o; for (int i = 0; i < count; i++) { thread.sleep(1000); print(i); } } /// <summary> /// 对象池 /// </summary> private void fun3(object o) { //int[] arr = (int[])o; //int count = (int)o; for (int i = 0; i < 5; i++) { thread.sleep(1000);//模拟此时操作一分钟 print(i);//主线程 卡 指的就是生命周期 } } /// <summary> /// 死循环 怎么办 /// </summary> private void fun4() { int n = 0; while (true) { thread.sleep(1000); print(++n); } } /// <summary> /// 退出线程 /// </summary> private void onapplicationquit() { //thread.abort(); //结束线程 //主线程卡顿的情况 可以开辟新的线程 } /// <summary> /// 信号灯 /// </summary> private manualresetevent signal; private void start() { //信号灯 绿灯行 红灯停 signal = new manualresetevent(true); //true表示绿灯 false 表示红灯 thread = new thread(fun1); thread.start(); } private void ongui() { if (guilayout.button("线程暂停")) { signal.reset(); } if (guilayout.button("线程继续")) { signal.set(); } } }
thread
- 创建线程: 创建thread类的一个对象,分配一个线程工作方法 。
thread thread = new thread(工作方法);
- 启动线程:start方法。
thread.start();
- 终止线程:工作方法自然退出、线程终止。
thread. abort ();
threadpool
在频繁创建和销毁线程时使用线程池技术,可以有效减少时间以及系统资源的开销。
threadpool.queueuserworkitem(工作方法);
前/后台线程
前台线程:程序必须等待所有前台线程结束后才能退出。(只要有一个前台线程未退出,进程就不会终止!即说的就是程序不会关闭!)[thread创建的线程默认前台线程]
后台线程:程序不考虑后台线程,后台线程随程序退出而结束。[threadpool创建的线程默认后台线程]
备注:unity程序退出后,前台线程也随即关闭。
新建的子线程可以是前台线程或者后台线程,前台线程必须全部执行完,即使主线程关闭掉,这时进程仍然存活。
线程状态
未启动状态 unstarted:创建线程对象。
运行状态running:执行绑定的方法。
等待睡眠阻塞状态 waitsleepjoin:暂时停止执行,资源交给其他线程使用。
终止状态 stopped:线程销毁。
using system.collections; using system.collections.generic; using unityengine; using system; using unityengine.ui; using system.threading; public class threaddemo : monobehaviour { private int second = 60; private text text; private void start() { text = getcomponent<text>(); thread thread = new thread(timer); thread.start(); } private void update() { if (action!=null) { action(); action = null; } } private void timer() { while (second>0) { thread.sleep(1000);//睡一会 期间没有cpu的调度 action = () => { second--; text.text = string.format("{0:d2}:{1:d2}", second / 60, second % 60); }; } } private action action; }
线程同步
需要同步的原因:
多个线程同一时刻访问共享资源(线程共享实例变量,静态变量),由于每个线程都不知道其他线程的操作,结果将产生不可预知的数据损坏。
同步:
线程之间相互等待排队执行。
如何同步:
将需要同步的代码用关键字lock锁定,锁定后该代码对于线程来讲就是独占使用的。当其他线程试图进入被锁定的临界区时,只能等待解锁后才可访问。因此锁定代码时是排队访问的,所以叫线程同步。
lock锁原理:
对象在堆中的分配:实例成员、同步块索引 (默认索引-1)、类型指针(指向类型对象)。
对象上锁后,同步索引块会指向同步块数组中的一个对象。
当其他对象执行lock的时候会等待该对象同步索引设置为-1。
using system.collections; using system.collections.generic; using unityengine; using system.threading; public class bank { public static int money = 1; public static object o = new object(); //必须使用引用类型 //优先使用object public static void get(int val) { lock (o)//-1 0 只有是-1的时候 锁打开 否则锁关闭 { //同步块索引 类型对象指针 //共享读 独占写 //枷锁(对象) 流程 if (money >= val) { //线程冲突 0 -1 -2 如何解决???加锁 thread.sleep(1000); money -= val; debug.log("取钱成功!余额:" + money); } else { debug.log("取钱失败!余额:" + money); } //线程离开代码块 索引块 设置为-1 } } } public class threaddemo2 : monobehaviour { private void start() { //bank.get(1); //同步调用 排队 threadpool.queueuserworkitem(o => { bank.get(1); }); ////线程调用(多线程) 不排队 } }
上一篇: 飞扬军事论坛宣布服务器将关停、停止运营