这里将记录一些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.
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.
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