一个有趣的Unity多线程练习例子

这篇博客探讨了C#线程在Unity中的应用,特别是Monitor、Mutex、lock和Semaphore的区别与用法。文章通过一个下载线程的例子和生产消费者模式来阐述如何在Unity中实现多线程同步,并强调了使用Monitor和lock进行线程控制的策略。
摘要由CSDN通过智能技术生成

这里将记录一些C#线程相关的信息,将持续更新,最总将形成一个工具类,方便在Unity中使用。

一些Tips:

1)Monitor VS. Mutex  

Difference between mutex and monitor. 

The biggest difference between the two is the scope: a mutex's scope is system-wide, whilst monitor's scope depends on the scope of the object you lock on. This means that with monitor, the widest scope you can get is generally application-wide.

So you would mostly use monitor to synchronise between threads running in an application, and use mutex to synchronise between different applications.

2)Monitor VS. lock

lock is just shortcut for Monitor.Enter with try + finally and Monitor.Exit. Use lock statement whenever it is enough - if you need something like TryEnter, you will have to use Monitor.

3)Semaphore VS. Monitors

Semaphore.WaitOne/Release vs Monitor.Pulse/Wait

Monitor.Wait and Monitor.Pulse are fundamental synchronization mechanisms that can be used to form pretty much any other synchronization device including semaphores.

结论,使用Monitor能够达到多线程的目的,lock可以简化这个过程。

4)Terminating a thread cleanly

5) Should a return statement be inside or outside a lock?

 At the IL level they are identical。

Only the current owner of the lock can signal a waiting object using Pulse.

The Pulse, PulseAll, and Wait methods must be invoked from within a synchronized block of code.

一个下载线程的例子:

 private class DownloadFactory {
        #region ===== 线程共享资源 =====
        private volatile bool isOpen;
        private Queue<DownloadJob> workingJobs = new Queue<DownloadJob>();
        private Queue<DownloadJob> finishedJobs = new Queue<DownloadJob>();
        #endregion

        const int WORK_NUM = 5; // 开启5个下载线程
        private Thread[] workers; // 工作线程,负责下载
        private Thread checker;  // 检测线程, 用来写磁盘或则重新下载

        public DownloadFactory() {
            isOpen = false;

            workers = new Thread[WORK_NUM];
            for (int i = 0; i < WORK_NUM; i++) { 
                workers[i] = new Thread(() => {
                    while (isOpen) {
                        var job = takeJob();
                        // do download affairs!
                        finJob(job);
                    }
                });
            }

            checker = new Thread(() => {
                while (isOpen) {
                    var job = checkJob();
                    if (!job.isOK) {  // 下载不成功,则重新下载
                        putJob(job);
                    } else { // 写文件操作

                    }
                }
            });
        }

        public bool isDone {
            get {
                return totalCount == 0;
            }
        }

        // 开始
        public void Open(Queue<DownloadJob> _allJobs) {
            workingJobs = _allJobs;
            isOpen = true;
            checker.Start();
            foreach (var w in workers) {
                w.Start();
            }
        }

        // 结束
        public void Close() {
            isOpen = false;
            checker.Interrupt();
            foreach (var w in workers) {
                w.Interrupt();
            }
            checker.Join();
            foreach (var w in workers) {
                w.Join();
            }
        }

        #region ========= 线程同步逻辑 ===========
        private int totalCount {
            get {
                lock (this) {
                    return workingJobs.Count + finishedJobs.Count;
                }
            }
        }

        private DownloadJob takeJob() {
            lock (this) {
                while (workingJobs.Count <= 0) {
                    Monitor.Wait(this);
                }
                var rt = workingJobs.Dequeue();
                Monitor.PulseAll(this);
                return rt;
            }
        }

        private void putJob(DownloadJob job) {
            lock (this) {
                workingJobs.Enqueue(job);
                Monitor.PulseAll(this);
            }
        }

        private void finJob(DownloadJob job) {
            lock (this) {
                finishedJobs.Enqueue(job);
                Monitor.PulseAll(this);
            }
        }

        private DownloadJob checkJob() {
            lock(this) {
                while (finishedJobs.Count <= 0) {
                    Monitor.Wait(this);
                }
                var job = finishedJobs.Dequeue();
                Monitor.PulseAll(this);
                return job;
            }
        }
        #endregion
    }

例子:生产消费者模式

using UnityEngine;
using
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值