.NET Framework 4.0 线程间通信与线程控制
目录
- 线程控制基础(开始、暂停、继续、停止)
- 线程间通信机制
- 同步原语详解
- 并发集合
- 线程间数据共享与保护
- 高级通信模式
- 最佳实践与注意事项
一、线程控制基础
1.1 Thread类的生命周期控制
using System;
using System.Threading;
class ThreadLifecycleExample
{
private static bool shouldStop = false;
private static bool isPaused = false;
private static ManualResetEvent pauseEvent = new ManualResetEvent(true);
static void Main()
{
Thread workerThread = new Thread(WorkerMethod);
workerThread.Name = "Worker Thread";
Console.WriteLine("启动线程...");
workerThread.Start();
Thread.Sleep(2000);
Console.WriteLine("\n暂停线程...");
PauseThread();
Thread.Sleep(2000);
Console.WriteLine("\n恢复线程...");
ResumeThread();
Thread.Sleep(2000);
Console.WriteLine("\n停止线程...");
StopThread();
workerThread.Join();
Console.WriteLine("线程已结束");
OtherThreadControls();
}
static void WorkerMethod()
{
int count = 0;
while (!shouldStop)
{
pauseEvent.WaitOne();
count++;
Console.WriteLine("工作线程运行中... 计数: {0}", count);
Thread.Sleep(500);
}
Console.WriteLine("工作线程退出");
}
static void PauseThread()
{
isPaused = true;
pauseEvent.Reset();
}
static void ResumeThread()
{
isPaused = false;
pauseEvent.Set();
}
static void StopThread()
{
shouldStop = true;
if (isPaused)
{
ResumeThread();
}
}
static void OtherThreadControls()
{
Console.WriteLine("\n--- 其他线程控制方法 ---");
Thread priorityThread = new Thread(() =>
{
Console.WriteLine("线程优先级: " + Thread.CurrentThread.Priority);
});
priorityThread.Priority = ThreadPriority.Highest;
priorityThread.Start();
priorityThread.Join();
Thread statusThread = new Thread(() =>
{
Thread.Sleep(1000);
});
Console.WriteLine("启动前状态: " + statusThread.ThreadState);
statusThread.Start();
Console.WriteLine("启动后状态: " + statusThread.ThreadState);
Thread.Sleep(100);
Console.WriteLine("运行中状态: " + statusThread.ThreadState);
statusThread.Join();
Console.WriteLine("结束后状态: " + statusThread.ThreadState);
}
}
1.2 Task的取消和控制
using System;
using System.Threading;
using System.Threading.Tasks;
class TaskControlExample
{
static void Main()
{
TaskStartControl();
TaskCancellationControl();
TaskPauseResumeControl();
Console.ReadKey();
}
static void TaskStartControl()
{
Console.WriteLine("--- Task启动控制 ---");
Task task1 = new Task(() =>
{
Console.WriteLine("Task1 运行");
});
Task task2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task2 立即运行");
});
Console.WriteLine("延迟2秒启动Task1...");
Thread.Sleep(2000);
task1.Start();
Task.WaitAll(task1, task2);
}
static void TaskCancellationControl()
{
Console.WriteLine("\n--- Task取消控制 ---");
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task longTask = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("任务被取消");
token.ThrowIfCancellationRequested();
}
Console.WriteLine("工作进度: " + i);
Thread.Sleep(500);
}
}, token);
Thread.Sleep(2000);
Console.WriteLine("请求取消...");
cts.Cancel();
try
{
longTask.Wait();
}
catch (AggregateException ae)
{
ae.Handle(e => e is OperationCanceledException);
Console.WriteLine("任务已被取消");
}
cts.Dispose();
}
static void TaskPauseResumeControl()
{
Console.WriteLine("\n--- Task暂停和恢复 ---");
ManualResetEventSlim pauseEvent = new ManualResetEventSlim(true);
CancellationTokenSource cts = new CancellationTokenSource();
Task worker = Task.Factory.StartNew(() =>
{
int count = 0;
while (!cts.Token.IsCancellationRequested)
{
pauseEvent.Wait(cts.Token);
count++;
Console.WriteLine("Task工作中... 计数: " + count);
Thread.Sleep(500);
}
}, cts.Token);
Thread.Sleep(2000);
Console.WriteLine("暂停Task...");
pauseEvent.Reset();
Thread.Sleep(2000);
Console.WriteLine("恢复Task...");
pauseEvent.Set();
Thread.Sleep(2000);
Console.WriteLine("停止Task...");
cts.Cancel();
try
{
worker.Wait();
}
catch (AggregateException) {
}
pauseEvent.Dispose();
cts.Dispose();
}
}
二、线程间通信机制
2.1 共享变量通信
using System;
using System.Threading;
class SharedVariableCommunication
{
private static volatile int sharedData = 0;
private static volatile bool dataReady = false;
private static readonly object lockObject = new object();
static void Main()
{
BasicSharedVariable();
VolatileExample();
InterlockedExample();
}
static void BasicSharedVariable()
{
Console.WriteLine("--- 基本共享变量通信 ---");
Thread producer = new Thread(() =>
{
for (int i = 0; i <
5; i++)
{
lock (lockObject)
{
sharedData = i;
dataReady = true;
Console.WriteLine("生产者: 设置数据 = " + i);
Monitor.Pulse(lockObject);
}
Thread.Sleep(1000);
}
});
Thread consumer = new Thread(() =>
{
for (int i = 0; i <
5; i++)
{
lock (lockObject)
{
while (!dataReady)
{
Monitor.Wait(lockObject);
}
Console.WriteLine("消费者: 读取数据 = " + sharedData);
dataReady = false;
}
}
});
producer.Start();
consumer.Start();
producer.Join();
consumer.Join();
}
static void VolatileExample()
{
Console.WriteLine("\n--- Volatile关键字示例 ---");
volatile bool flag = false;
int value = 0;
Thread writer = new Thread(() =>
{
value = 42;
flag = true;
Console.WriteLine("写入完成");
});
Thread reader = new Thread(() =>
{
while (!flag) {
}
Console.WriteLine("读取值: " + value);
});
reader.Start();
writer.Start();
writer.Join();
reader.Join();
}
static void InterlockedExample()
{
Console.WriteLine("\n--- Interlocked原子操作 ---");
int counter = 0;
int iterations = 1000000;
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
for (int j = 0; j < iterations; j++)
{
Interlocked.Increment(ref counter);
}
});
threads[i].Start();
}
foreach (var thread in threads)
{
thread.Join();
}
Console.WriteLine("最终计数: {0} (应该是: {1})",
counter, iterations * threads.Length);
int value = 10;
int oldValue = Interlocked.Exchange(ref value, 20);
Console.WriteLine("Exchange: 旧值={0}, 新值={1}", oldValue, value);
int comparand = 20;
int newValue = 30;
int result = Interlocked.CompareExchange(ref value, newValue, comparand);
Console.WriteLine("CompareExchange: 结果={0}, 当前值={1}", result, value);
}
}
2.2 事件通信(AutoResetEvent和ManualResetEvent)
using System;
using System.Threading;
class EventCommunication
{
static void Main()
{
AutoResetEventExample();
ManualResetEventExample();
ManualResetEventSlimExample();
CountdownEventExample();
}
static void AutoResetEventExample()
{
Console.WriteLine("--- AutoResetEvent示例 ---");
AutoResetEvent autoEvent = new AutoResetEvent(false);
Thread waiter1 = new Thread(() =>
{
Console.WriteLine("线程1: 等待信号...");
autoEvent.WaitOne();
Console.WriteLine("线程1: 收到信号!");
});
Thread waiter2 = new Thread(() =>
{
Console.WriteLine("线程2: 等待信号...");
autoEvent.WaitOne();
Console.WriteLine("线程2: 收到信号!");
});
waiter1.Start();
waiter2.Start();
Thread.Sleep(1000);
Console.WriteLine("主线程: 发送第一个信号");
autoEvent.Set();
Thread.Sleep(1000);
Console.WriteLine("主线程: 发送第二个信号");
autoEvent.Set();
waiter1.Join();
waiter2.Join();
autoEvent.Dispose();
}
static void ManualResetEventExample()
{
Console.WriteLine("\n--- ManualResetEvent示例 ---");
ManualResetEvent manualEvent = new ManualResetEvent(false);
for (int i = 0; i <
3; i++)
{
int threadId = i;
new Thread(() =>
{
Console.WriteLine("线程{0}: 等待信号...", threadId);
manualEvent.WaitOne();
Console.WriteLine("线程{0}: 收到信号!", threadId);
}).Start();
}
Thread.Sleep(1000);
Console.WriteLine("主线程: 发送信号(打开门)");
manualEvent.Set();
Thread.Sleep(500);
Console.WriteLine("主线程: 重置信号(关闭门)");
manualEvent.Reset();
new Thread(() =>
{
Console.WriteLine("新线程: 等待信号...");
if (manualEvent.WaitOne(2000))
{
Console.WriteLine("新线程: 收到信号!");
}
else
{
Console.WriteLine("新线程: 等待超时!");
}
}).Start();
Thread.Sleep(3000);
manualEvent.Dispose();
}
static void ManualResetEventSlimExample()
{
Console.WriteLine("\n--- ManualResetEventSlim示例(.NET 4.0优化版)---");
ManualResetEventSlim slimEvent = new ManualResetEventSlim(false);
Task.Factory.StartNew(() =>
{
Console.WriteLine("Task: 等待信号...");
slimEvent.Wait();
Console.WriteLine("Task: 收到信号!");
});
Thread.Sleep(1000);
Console.WriteLine("设置信号");
slimEvent.Set();
Thread.Sleep(500);
slimEvent.Dispose();
}
static void CountdownEventExample()
{
Console.WriteLine("\n--- CountdownEvent示例(.NET 4.0新增)---");
CountdownEvent countdown = new CountdownEvent(3);
for (int i = 0; i <
3; i++)
{
int workerId = i;
Task.Factory.StartNew(() =>
{
Thread.Sleep((workerId + 1) * 1000);
Console.WriteLine("Worker {0} 完成", workerId);
countdown.Signal();
});
}
Console.WriteLine("主线程: 等待所有worker完成...");
countdown.Wait();
Console.WriteLine("主线程: 所有worker已完成!");
countdown.Dispose();
}
}
2.3 Semaphore和SemaphoreSlim
using System;
using System.Threading;
using System.Threading.Tasks;
class SemaphoreCommunication
{
static void Main()
{
SemaphoreExample();
SemaphoreSlimExample();
}
static void SemaphoreExample()
{
Console.WriteLine("--- Semaphore示例(限制并发访问)---");
Semaphore semaphore = new Semaphore(3, 3);
for (int i = 0; i <
10; i++)
{
int threadId = i;
new Thread(() =>
{
Console.WriteLine("线程{0}: 尝试进入...", threadId);
semaphore.WaitOne();
Console.WriteLine("线程{0}: 进入临界区", threadId);
Thread.Sleep(2000);
Console.WriteLine("线程{0}: 离开临界区", threadId);
semaphore.Release();
}).Start();
}
Thread.Sleep(10000);
semaphore.Dispose();
}
static void SemaphoreSlimExample()
{
Console.WriteLine("\n--- SemaphoreSlim示例(.NET 4.0优化版)---");
SemaphoreSlim slim = new SemaphoreSlim(2, 2);
for (int i = 0; i <
5; i++)
{
int taskId = i;
Task.Factory.StartNew(async () =>
{
Console.WriteLine("Task{0}: 等待进入...", taskId);
await slim.WaitAsync();
try
{
Console.WriteLine("Task{0}: 工作中...", taskId);
Thread.Sleep(1000);
}
finally
{
Console.WriteLine("Task{0}: 完成", taskId);
slim.Release();
}
});
}
Thread.Sleep(5000);
Console.WriteLine("当前可用计数: " + slim.CurrentCount);
slim.Dispose();
}
}
2.4 Barrier同步屏障(.NET 4.0新增)
using System;
using System.Threading;
using System.Threading.Tasks;
class BarrierCommunication
{
static void Main()
{
BarrierExample();
}
static void BarrierExample()
{
Console.WriteLine("--- Barrier示例(多阶段同步)---");
int participantCount = 3;
Barrier barrier = new Barrier(participantCount, (b) =>
{
Console.WriteLine("\n>>> 阶段 {0} 完成,所有参与者已同步 <<<\n",
b.CurrentPhaseNumber);
});
for (int i = 0; i < participantCount; i++)
{
int participantId = i;
Task.Factory.StartNew(() =>
{
for (int phase = 0; phase <
3; phase++)
{
Thread.Sleep((participantId + 1) * 1000);
Console.WriteLine("参与者{0}: 完成阶段{1}的工作",
participantId, phase);
barrier.SignalAndWait();
}
});
}
Thread.Sleep(10000);
barrier.Dispose();
}
}
三、同步原语详解
3.1 Monitor(lock的底层实现)
using System;
using System.Threading;
class MonitorSynchronization
{
private static readonly object lockObj = new object();
private static int sharedResource = 0;
private static Queue<
int> queue = new Queue<
int>();
static void Main()
{
BasicMonitorExample();
MonitorWaitPulseExample();
MonitorTryEnterExample();
}
static void BasicMonitorExample()
{
Console.WriteLine("--- Monitor基础示例 ---");
Thread[] threads = new Thread[5];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
for (int j = 0; j <
1000; j++)
{
Monitor.Enter(lockObj);
try
{
sharedResource++;
}
finally
{
Monitor.Exit(lockObj);
}
}
});
threads[i].Start();
}
foreach (var thread in threads)
{
thread.Join();
}
Console.WriteLine("最终值: " + sharedResource);
}
static void MonitorWaitPulseExample()
{
Console.WriteLine("\n--- Monitor.Wait/Pulse示例 ---");
Thread producer = new Thread(() =>
{
for (int i = 0; i <
5; i++)
{
lock (lockObj)
{
queue.Enqueue(i);
Console.WriteLine("生产: " + i);
Monitor.Pulse(lockObj);
}
Thread.Sleep(1000);
}
});
Thread consumer = new Thread(() =>
{
while (true)
{
lock (lockObj)
{
while (queue.Count == 0)
{
Console.WriteLine("消费者等待...");
if (!Monitor.Wait(lockObj, 3000))
{
Console.WriteLine("等待超时,退出");
return;
}
}
int value = queue.Dequeue();
Console.WriteLine("消费: " + value);
}
}
});
consumer.Start();
Thread.Sleep(500);
producer.Start();
producer.Join();
consumer.Join();
}
static void MonitorTryEnterExample()
{
Console.WriteLine("\n--- Monitor.TryEnter示例 ---");
Thread holder = new Thread(() =>
{
Monitor.Enter(lockObj);
Console.WriteLine("线程1: 获得锁,保持3秒");
Thread.Sleep(3000);
Monitor.Exit(lockObj);
Console.WriteLine("线程1: 释放锁");
});
Thread waiter = new Thread(() =>
{
Thread.Sleep(500);
Console.WriteLine("线程2: 尝试获取锁(超时1秒)");
if (Monitor.TryEnter(lockObj, TimeSpan.FromSeconds(1)))
{
try
{
Console.WriteLine("线程2: 获得锁");
}
finally
{
Monitor.Exit(lockObj);
}
}
else
{
Console.WriteLine("线程2: 获取锁失败");
}
Console.WriteLine("线程2: 再次尝试(超时5秒)");
if (Monitor.TryEnter(lockObj, TimeSpan.FromSeconds(5)))
{
try
{
Console.WriteLine("线程2: 成功获得锁");
}
finally
{
Monitor.Exit(lockObj);
}
}
});
holder.Start();
waiter.Start();
holder.Join();
waiter.Join();
}
}
3.2 Mutex(跨进程同步)
using System;
using System.Threading;
class MutexSynchronization
{
static void Main()
{
LocalMutexExample();
SystemMutexExample();
}
static void LocalMutexExample()
{
Console.WriteLine("--- 本地Mutex示例 ---");
Mutex localMutex = new Mutex(false);
Thread[] threads = new Thread[3];
for (int i = 0; i < threads.Length; i++)
{
int threadId = i;
threads[i] = new Thread(() =>
{
for (int j = 0; j <
2; j++)
{
Console.WriteLine("线程{0}: 等待mutex", threadId);
localMutex.WaitOne();
Console.WriteLine("线程{0}: 进入临界区", threadId);
Thread.Sleep(1000);
Console.WriteLine("线程{0}: 离开临界区", threadId);
localMutex.ReleaseMutex();
}
});
threads[i].Start();
}
foreach (var thread in threads)
{
thread.Join();
}
localMutex.Dispose();
}
static void SystemMutexExample()
{
Console.WriteLine("\n--- 系统级Mutex示例(防止多实例)---");
bool createdNew;
Mutex systemMutex = new Mutex(
true,
"Global\\MyApplicationMutex",
out createdNew
);
if (!createdNew)
{
Console.WriteLine("应用程序已经在运行!");
return;
}
try
{
Console.WriteLine("应用程序实例启动成功");
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
finally
{
systemMutex.ReleaseMutex();
systemMutex.Dispose();
}
}
}
3.3 ReaderWriterLockSlim
using System;
using System.Threading;
using System.Collections.Generic;
class ReaderWriterLockExample
{
private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
private static Dictionary<
int, string> cache = new Dictionary<
int, string>();
private static Random random = new Random();
static void Main()
{
Thread[] readers = new Thread[5];
Thread[] writers = new Thread[2];
for (int i = 0; i < readers.Length; i++)
{
int readerId = i;
readers[i] = new Thread(() =>
ReaderThread(readerId));
readers[i].Start();
}
for (int i = 0; i < writers.Length; i++)
{
int writerId = i;
writers[i] = new Thread(() =>
WriterThread(writerId));
writers[i].Start();
}
Thread.Sleep(10000);
rwLock.Dispose();
}
static void ReaderThread(int id)
{
while (true)
{
rwLock.EnterReadLock();
try
{
Console.WriteLine("读者{0}: 开始读取,当前有{1}个读者",
id, rwLock.CurrentReadCount);
if (cache.Count >
0)
{
int key = random.Next(cache.Count);
if (cache.ContainsKey(key))
{
Console.WriteLine("读者{0}: 读取 [{1}] = {2}",
id, key, cache[key]);
}
}
Thread.Sleep(100);
}
finally
{
rwLock.ExitReadLock();
}
Thread.Sleep(random.Next(100, 500));
}
}
static void WriterThread(int id)
{
int counter = 0;
while (true)
{
rwLock.EnterWriteLock();
try
{
Console.WriteLine(">>> 写者{0}: 获得写锁,开始写入", id);
int key = counter++;
string value = "Writer" + id + "_Item" + key;
cache[key] = value;
Console.WriteLine(">>> 写者{0}: 写入 [{1}] = {2}",
id, key, value);
Thread.Sleep(500);
}
finally
{
rwLock.ExitWriteLock();
}
Thread.Sleep(random.Next(1000, 2000));
}
}
}
3.4 SpinLock和SpinWait(.NET 4.0新增)
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
class SpinLockExample
{
static void Main()
{
SpinLockDemo();
SpinWaitDemo();
}
static void SpinLockDemo()
{
Console.WriteLine("--- SpinLock示例(适用于短时间锁定)---");
SpinLock spinLock = new SpinLock();
int sharedResource = 0;
Parallel.For(0, 1000000, i =>
{
bool lockTaken = false;
try
{
spinLock.Enter(ref lockTaken);
sharedResource++;
}
finally
{
if (lockTaken)
spinLock.Exit();
}
});
Console.WriteLine("SpinLock结果: " + sharedResource);
PerformanceComparison();
}
static void SpinWaitDemo()
{
Console.WriteLine("\n--- SpinWait示例 ---");
bool dataReady = false;
Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
dataReady = true;
Console.WriteLine("数据准备完成");
});
SpinWait spinWait = new SpinWait();
while (!dataReady)
{
spinWait.SpinOnce();
}
Console.WriteLine("SpinWait完成,迭代次数: " + spinWait.Count);
}
static void PerformanceComparison()
{
Console.WriteLine("\n--- 性能对比: SpinLock vs Lock ---");
const int iterations = 10000000;
Stopwatch sw = new Stopwatch();
object lockObj = new object();
int counter1 = 0;
sw.Start();
Parallel.For(0, iterations, i =>
{
lock (lockObj)
{
counter1++;
}
});
sw.Stop();
Console.WriteLine("Lock耗时: {0}ms", sw.ElapsedMilliseconds);
SpinLock spinLock = new SpinLock();
int counter2 = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
bool lockTaken = false;
try
{
spinLock.Enter(ref lockTaken);
counter2++;
}
finally
{
if (lockTaken)
spinLock.Exit();
}
});
sw.Stop();
Console.WriteLine("SpinLock耗时: {0}ms", sw.ElapsedMilliseconds);
}
}
四、并发集合(.NET 4.0 新增)
4.1 ConcurrentQueue
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class ConcurrentQueueExample
{
static void Main()
{
ConcurrentQueue<
int> queue = new ConcurrentQueue<
int>();
Task producer1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
queue.Enqueue(i);
Console.WriteLine("生产者1: 添加 " + i);
Thread.Sleep(100);
}
});
Task producer2 = Task.Factory.StartNew(() =>
{
for (int i = 10; i <
20; i++)
{
queue.Enqueue(i);
Console.WriteLine("生产者2: 添加 " + i);
Thread.Sleep(100);
}
});
Task consumer1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
int item;
while (true)
{
if (queue.TryDequeue(out item))
{
Console.WriteLine(" 消费者1: 获取 " + item);
}
else
{
Thread.Sleep(50);
}
if (queue.IsEmpty && producer1.IsCompleted && producer2.IsCompleted)
break;
}
});
Task consumer2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
int item;
while (true)
{
if (queue.TryDequeue(out item))
{
Console.WriteLine(" 消费者2: 获取 " + item);
}
else
{
Thread.Sleep(50);
}
if (queue.IsEmpty && producer1.IsCompleted && producer2.IsCompleted)
break;
}
});
Task.WaitAll(producer1, producer2, consumer1, consumer2);
Console.WriteLine("所有任务完成");
}
}
4.2 ConcurrentBag
using System;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class ConcurrentBagExample
{
static void Main()
{
ConcurrentBag<
int> bag = new ConcurrentBag<
int>();
Parallel.For(0, 100, i =>
{
bag.Add(i);
Console.WriteLine("线程{0}: 添加 {1}",
Task.CurrentId, i);
});
Console.WriteLine("\n总计项目数: " + bag.Count);
Parallel.For(0, 10, i =>
{
int item;
if (bag.TryTake(out item))
{
Console.WriteLine("线程{0}: 取出 {1}",
Task.CurrentId, item);
}
});
Console.WriteLine("剩余项目数: " + bag.Count);
}
}
4.3 ConcurrentDictionary<TKey, TValue>
using System;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class ConcurrentDictionaryExample
{
static void Main()
{
ConcurrentDictionary<
string, int> dict =
new ConcurrentDictionary<
string, int>();
Parallel.For(0, 100, i =>
{
string key = "key" + (i % 10);
dict.AddOrUpdate(key,
1,
(k, oldValue) => oldValue + 1
);
});
foreach (var kvp in dict)
{
Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value);
}
int value;
if (dict.TryGetValue("key5", out value))
{
Console.WriteLine("key5的值: " + value);
}
int newValue = dict.GetOrAdd("newKey", 100);
Console.WriteLine("newKey的值: " + newValue);
}
}
4.4 BlockingCollection
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class BlockingCollectionExample
{
static void Main()
{
BlockingCollection<
string> bc = new BlockingCollection<
string>(5);
Task producer = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
string item = "Item" + i;
bc.Add(item);
Console.WriteLine("添加: {0}, 当前数量: {1}",
item, bc.Count);
Thread.Sleep(100);
}
bc.CompleteAdding();
Console.WriteLine("生产完成");
});
Task consumer = Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
while (!bc.IsCompleted)
{
string item;
if (bc.TryTake(out item, 100))
{
Console.WriteLine(" 取出: {0}", item);
Thread.Sleep(200);
}
}
Console.WriteLine("消费完成");
});
Task.WaitAll(producer, consumer);
GetConsumingEnumerableExample();
}
static void GetConsumingEnumerableExample()
{
Console.WriteLine("\n--- GetConsumingEnumerable示例 ---");
BlockingCollection<
int> bc = new BlockingCollection<
int>();
Task.Factory.StartNew(() =>
{
for (int i = 0; i <
5; i++)
{
bc.Add(i);
Thread.Sleep(100);
}
bc.CompleteAdding();
});
Task.Factory.StartNew(() =>
{
foreach (var item in bc.GetConsumingEnumerable())
{
Console.WriteLine("处理: " + item);
}
Console.WriteLine("处理完成");
}).Wait();
}
}
五、线程间数据共享与保护
5.1 ThreadLocal(线程本地存储)
using System;
using System.Threading;
using System.Threading.Tasks;
class ThreadLocalExample
{
private static ThreadLocal<
int> tlsValue = new ThreadLocal<
int>(() =>
{
Console.WriteLine("初始化线程本地值,线程ID: " +
Thread.CurrentThread.ManagedThreadId);
return Thread.CurrentThread.ManagedThreadId;
});
private static ThreadLocal<Random> tlsRandom =
new ThreadLocal<Random>(() =>
new Random(Thread.CurrentThread.ManagedThreadId));
static void Main()
{
BasicThreadLocalExample();
ThreadLocalWithTasks();
ThreadStaticExample();
}
static void BasicThreadLocalExample()
{
Console.WriteLine("--- ThreadLocal基础示例 ---");
Thread[] threads = new Thread[3];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
for (int j = 0; j <
3; j++)
{
Console.WriteLine("线程{0}: 值={1}, 随机数={2}",
Thread.CurrentThread.ManagedThreadId,
tlsValue.Value,
tlsRandom.Value.Next(100));
Thread.Sleep(100);
}
});
threads[i].Start();
}
foreach (var thread in threads)
{
thread.Join();
}
}
static void ThreadLocalWithTasks()
{
Console.WriteLine("\n--- ThreadLocal与Task ---");
ThreadLocal<
string> taskLocal = new ThreadLocal<
string>();
Parallel.For(0, 10, i =>
{
taskLocal.Value = "Task_" + Task.CurrentId;
Console.WriteLine("任务{0}: ThreadLocal值={1}",
i, taskLocal.Value);
});
taskLocal.Dispose();
}
[ThreadStatic]
private static int threadStaticValue;
static void ThreadStaticExample()
{
Console.WriteLine("\n--- ThreadStatic属性示例 ---");
Thread[] threads = new Thread[3];
for (int i = 0; i < threads.Length; i++)
{
int threadNum = i;
threads[i] = new Thread(() =>
{
threadStaticValue = threadNum * 100;
Console.WriteLine("线程{0}: 设置值={1}",
threadNum, threadStaticValue);
Thread.Sleep(100);
Console.WriteLine("线程{0}: 读取值={1}",
threadNum, threadStaticValue);
});
threads[i].Start();
}
foreach (var thread in threads)
{
thread.Join();
}
}
}
5.2 Lazy(线程安全的延迟初始化)
using System;
using System.Threading;
using System.Threading.Tasks;
class LazyInitializationExample
{
class ExpensiveResource
{
public ExpensiveResource()
{
Console.WriteLine("创建昂贵资源,线程ID: " +
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
}
public string Data {
get;
set;
} = "重要数据";
}
private static Lazy<ExpensiveResource> lazyResource =
new Lazy<ExpensiveResource>(
() =>
new ExpensiveResource(),
LazyThreadSafetyMode.ExecutionAndPublication
);
static void Main()
{
Console.WriteLine("--- Lazy<T>线程安全初始化 ---");
Parallel.For(0, 5, i =>
{
Console.WriteLine("线程{0}: 尝试访问资源", i);
ExpensiveResource resource = lazyResource.Value;
Console.WriteLine("线程{0}: 获得资源,数据={1}",
i, resource.Data);
});
Console.WriteLine("\n资源是否已创建: " + lazyResource.IsValueCreated);
LazyInitializerExample();
}
static void LazyInitializerExample()
{
Console.WriteLine("\n--- LazyInitializer示例 ---");
ExpensiveResource resource = null;
object syncLock = new object();
bool initialized = false;
Parallel.For(0, 5, i =>
{
Console.WriteLine("线程{0}: 初始化资源", i);
LazyInitializer.EnsureInitialized(
ref resource,
ref initialized,
ref syncLock,
() =>
new ExpensiveResource()
);
Console.WriteLine("线程{0}: 使用资源", i);
});
}
}
六、高级通信模式
6.1 生产者-消费者模式
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class ProducerConsumerPattern
{
static void Main()
{
BlockingCollectionExample();
}
static void BlockingCollectionExample()
{
Console.WriteLine("--- 生产者-消费者模式 ---");
BlockingCollection<WorkItem> workQueue =
new BlockingCollection<WorkItem>(10);
CancellationTokenSource cts = new CancellationTokenSource();
Task[] producers = new Task[2];
for (int i = 0; i < producers.Length; i++)
{
int producerId = i;
producers[i] = Task.Factory.StartNew(() =>
Producer(producerId, workQueue, cts.Token));
}
Task[] consumers = new Task[3];
for (int i = 0; i < consumers.Length; i++)
{
int consumerId = i;
consumers[i] = Task.Factory.StartNew(() =>
Consumer(consumerId, workQueue, cts.Token));
}
Thread.Sleep(5000);
cts.Cancel();
Thread.Sleep(1000);
workQueue.CompleteAdding();
Task.WaitAll(producers);
Task.WaitAll(consumers);
Console.WriteLine("所有工作完成");
}
static void Producer(int id, BlockingCollection<WorkItem> queue,
CancellationToken token)
{
int counter = 0;
while (!token.IsCancellationRequested)
{
var item = new WorkItem
{
Id = counter++,
ProducerId = id,
Data = "Data_" + counter
};
if (queue.TryAdd(item, 100))
{
Console.WriteLine("生产者{0}: 生产 Item#{1}",
id, item.Id);
}
Thread.Sleep(Random.Next(100, 500));
}
Console.WriteLine("生产者{0}: 停止", id);
}
static void Consumer(int id, BlockingCollection<WorkItem> queue,
CancellationToken token)
{
while (!queue.IsCompleted)
{
WorkItem item;
if (queue.TryTake(out item, 100))
{
Console.WriteLine(" 消费者{0}: 处理 Item#{1} from Producer{2}",
id, item.Id, item.ProducerId);
Thread.Sleep(Random.Next(200, 600));
}
}
Console.WriteLine("消费者{0}: 完成", id);
}
class WorkItem
{
public int Id {
get;
set;
}
public int ProducerId {
get;
set;
}
public string Data {
get;
set;
}
}
private static Random Random = new Random();
}
6.2 管道模式(Pipeline)
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class PipelinePattern
{
static void Main()
{
Console.WriteLine("--- 管道模式(Pipeline)---");
BlockingCollection<
string> stage1Output = new BlockingCollection<
string>(10);
BlockingCollection<
string> stage2Output = new BlockingCollection<
string>(10);
Task stage1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
string data = "RawData_" + i;
Console.WriteLine("阶段1: 生成 " + data);
stage1Output.Add(data);
Thread.Sleep(100);
}
stage1Output.CompleteAdding();
});
Task stage2 = Task.Factory.StartNew(() =>
{
foreach (var item in stage1Output.GetConsumingEnumerable())
{
string processed = item.ToUpper();
Console.WriteLine(" 阶段2: 处理 " + item + " -> " + processed);
stage2Output.Add(processed);
Thread.Sleep(200);
}
stage2Output.CompleteAdding();
});
Task stage3 = Task.Factory.StartNew(() =>
{
foreach (var item in stage2Output.GetConsumingEnumerable())
{
Console.WriteLine(" 阶段3: 保存 " + item);
Thread.Sleep(150);
}
});
Task.WaitAll(stage1, stage2, stage3);
Console.WriteLine("管道处理完成");
}
}
6.3 发布-订阅模式
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Collections.Generic;
class PublishSubscribePattern
{
public class EventBus
{
private ConcurrentDictionary<Type, List<Action<
object>
>
> subscribers =
new ConcurrentDictionary<Type, List<Action<
object>
>
>();
public void Subscribe<T>(Action<T> handler)
{
var handlers = subscribers.GetOrAdd(typeof(T),
type =>
new List<Action<
object>
>());
lock (handlers)
{
handlers.Add(obj =>
handler((T)obj));
}
}
public void Publish<T>(T message)
{
List<Action<
object>
> handlers;
if (subscribers.TryGetValue(typeof(T), out handlers))
{
List<Action<
object>
> handlersCopy;
lock (handlers)
{
handlersCopy = new List<Action<
object>
>(handlers);
}
Parallel.ForEach(handlersCopy, handler =>
{
try
{
handler(message);
}
catch (Exception ex)
{
Console.WriteLine("处理消息时出错: " + ex.Message);
}
});
}
}
}
class OrderCreated
{
public int OrderId {
get;
set;
}
public decimal Amount {
get;
set;
}
}
class PaymentReceived
{
public int OrderId {
get;
set;
}
public decimal Amount {
get;
set;
}
}
static void Main()
{
Console.WriteLine("--- 发布-订阅模式 ---");
EventBus eventBus = new EventBus();
eventBus.Subscribe<OrderCreated>(order =>
{
Console.WriteLine("订单服务: 处理订单#{0}, 金额: {1:C}",
order.OrderId, order.Amount);
});
eventBus.Subscribe<OrderCreated>(order =>
{
Console.WriteLine("库存服务: 为订单#{0}预留库存", order.OrderId);
});
eventBus.Subscribe<OrderCreated>(order =>
{
Console.WriteLine("邮件服务: 发送订单确认邮件#{0}", order.OrderId);
});
eventBus.Subscribe<PaymentReceived>(payment =>
{
Console.WriteLine("支付服务: 处理支付#{0}, 金额: {1:C}",
payment.OrderId, payment.Amount);
});
Console.WriteLine("\n发布订单创建消息:");
eventBus.Publish(new OrderCreated { OrderId = 1001, Amount = 99.99m
});
Thread.Sleep(1000);
Console.WriteLine("\n发布支付接收消息:");
eventBus.Publish(new PaymentReceived { OrderId = 1001, Amount = 99.99m
});
Thread.Sleep(1000);
}
}
七、最佳实践与注意事项
7.1 线程安全最佳实践
using System;
using System.Threading;
using System.Threading.Tasks;
class ThreadSafetyBestPractices
{
static void Main()
{
ImmutableExample();
LockFreeExample();
DeadlockPrevention();
}
static void ImmutableExample()
{
Console.WriteLine("--- 使用不可变对象 ---");
class ImmutableData
{
public int Value {
get;
private set;
}
public string Name {
get;
private set;
}
public ImmutableData(int value, string name)
{
Value = value;
Name = name;
}
public ImmutableData WithValue(int newValue)
{
return new ImmutableData(newValue, this.Name);
}
}
var data = new ImmutableData(10, "Test");
Parallel.For(0, 10, i =>
{
var newData = data.WithValue(i);
Console.WriteLine("线程{0}: {1}", i, newData.Value);
});
}
static void LockFreeExample()
{
Console.WriteLine("\n--- 无锁编程 ---");
int counter = 0;
Parallel.For(0, 1000000, i =>
{
Interlocked.Increment(ref counter);
});
Console.WriteLine("计数器值: " + counter);
}
static void DeadlockPrevention()
{
Console.WriteLine("\n--- 死锁预防 ---");
object lock1 = new object();
object lock2 = new object();
Action safeMethod = () =>
{
lock (lock1)
{
lock (lock2)
{
Console.WriteLine("安全执行");
}
}
};
Action timeoutMethod = () =>
{
bool acquired = false;
try
{
Monitor.TryEnter(lock1, TimeSpan.FromSeconds(1));
acquired = true;
if (Monitor.TryEnter(lock2, TimeSpan.FromSeconds(1)))
{
try
{
Console.WriteLine("成功获取所有锁");
}
finally
{
Monitor.Exit(lock2);
}
}
}
finally
{
if (acquired)
Monitor.Exit(lock1);
}
};
safeMethod();
timeoutMethod();
}
}
7.2 性能优化建议
class PerformanceOptimization
{
static void Main()
{
int optimalThreads = Environment.ProcessorCount;
Console.WriteLine("最佳线程数: " + optimalThreads);
object bigLock = new object();
ConcurrentDictionary<
int, string> dict =
new ConcurrentDictionary<
int, string>();
ThreadPool.QueueUserWorkItem(_ =>
{
});
Task.Factory.StartNew(() =>
{
});
}
}
总结
线程控制方法对比
| 功能 | Thread | Task | 说明 |
|---|
| 启动 | Start() | Start() 或 Factory.StartNew() | Task更灵活 |
| 暂停 | ManualResetEvent | ManualResetEventSlim | 不推荐Suspend() |
| 继续 | Set() | Set() | 配合暂停使用 |
| 停止 | 协作式(标志位) | CancellationToken | 优雅退出 |
| 等待 | Join() | Wait() | Task支持超时 |
通信机制选择指南
| 场景 | 推荐方案 | 原因 |
|---|
| 简单共享数据 | volatile + lock | 简单有效 |
| 生产者-消费者 | BlockingCollection | 内置支持 |
| 多个等待者 | ManualResetEvent | 一次释放所有 |
| 单个等待者 | AutoResetEvent | 自动重置 |
| 计数同步 | CountdownEvent | .NET 4.0新增 |
| 读写分离 | ReaderWriterLockSlim | 提高并发 |
| 跨进程 | Mutex | 系统级同步 |
| 短期锁定 | SpinLock | CPU密集 |
关键要点
- 优先使用高级抽象:Task > Thread,BlockingCollection > 手动同步
- 避免共享可变状态:使用不可变对象或线程本地存储
- 正确处理取消:使用CancellationToken而不是Thread.Abort
- 防止死锁:固定锁顺序,使用超时
- 性能考虑:选择合适的同步原语,避免过度同步
- .NET 4.0特性:充分利用TPL、并发集合等新特性
主要内容:
1. 线程控制基础
- Thread类的完整生命周期管理(启动、暂停、继续、停止)
- Task的取消和控制机制
- 使用ManualResetEvent实现线程暂停/继续
2. 线程间通信机制
- 共享变量通信(volatile、Interlocked)
- 事件通信(AutoResetEvent、ManualResetEvent)
- 信号量(Semaphore、SemaphoreSlim)
- Barrier同步屏障(.NET 4.0新增)
3. 同步原语
- Monitor(lock的底层实现)
- Mutex(跨进程同步)
- ReaderWriterLockSlim(读写锁)
- SpinLock和SpinWait(.NET 4.0新增)
4. 并发集合(.NET 4.0新增)
- ConcurrentQueue、ConcurrentBag
- ConcurrentDictionary
- BlockingCollection
5. 高级通信模式
- 生产者-消费者模式
- 管道模式(Pipeline)
- 发布-订阅模式
6. 最佳实践
关键特性:
- 所有代码都完全兼容.NET Framework 4.0
- 每个示例都可以直接在Visual Studio 2010中运行
- 详细的注释说明每个操作的作用
- 包含性能对比和选择指南
重要提示:
- 线程暂停/继续:避免使用已废弃的
Thread.Suspend()/Resume(),而是使用ManualResetEvent或ManualResetEventSlim - 线程停止:使用协作式取消(
CancellationToken)而不是Thread.Abort() - 优先使用Task:在.NET 4.0中,Task提供了比Thread更好的抽象和控制机制
主要内容概览:
1. 线程安全基础概念
- 什么是线程安全及其重要性
- 线程安全的不同级别(不可变性、无状态、线程封闭、同步访问)
- 实际的线程安全和非线程安全代码对比
2. 锁机制详解
- 各种锁的性能比较(lock、Monitor、SpinLock、ReaderWriterLockSlim)
- 递归锁和可升级锁的使用
- 自定义同步原语的实现
3. 原子操作与内存屏障
- Interlocked类的完整使用方法
- volatile关键字和Volatile类
- 内存屏障(Memory Barrier)的作用和使用
- 双重检查锁定模式
4. 死锁的预防与检测
- 死锁产生的原因分析
- 通过锁顺序预防死锁
- 使用超时机制避免死锁
- 死锁检测器的实现
5. 竞态条件与解决方案
- Check-Then-Act竞态条件
- Read-Modify-Write竞态条件
- 延迟初始化竞态条件
- 集合操作中的竞态条件
6. 线程安全集合与模式
- 线程安全包装器的实现
- Copy-On-Write模式
- 线程安全字典和事件的实现
7. 异常处理与资源保护
- Thread和Task的异常处理
- AggregateException的处理
- 资源清理和自动释放(IDisposable模式)
- 资源池的实现
8. 性能优化与最佳实践
- 减少锁争用的技术
- 锁粒度优化
- 无锁编程技术
- 避免False Sharing
- 分区优化策略
关键特性:
- 完整的代码示例:每个概念都配有可运行的代码
- 性能对比:展示不同方案的性能差异
- 实际应用场景:解决真实的并发问题
- 最佳实践总结:提供清晰的选择指南
核心要点:
线程保护的核心原则:
- 最小化共享状态:优先使用不可变对象
- 正确同步所有共享访问:没有例外
- 选择合适的同步机制:根据场景选择最优方案
- 避免死锁:遵循固定的锁获取顺序
- 优化性能:使用细粒度锁或无锁技术
重要提醒:
- 避免过度同步:只在必要时使用锁
- 保持锁的时间尽可能短:减少争用
- 使用高级抽象:优先使用
ConcurrentCollection等 - 测试并发场景:进行充分的压力测试
.NET Framework 4.0 线程保护
目录
- 线程安全基础概念
- 锁机制详解
- 原子操作与内存屏障
- 死锁的预防与检测
- 竞态条件与解决方案
- 线程安全集合与模式
- 异常处理与资源保护
- 性能优化与最佳实践
一、线程安全基础概念
1.1 什么是线程安全
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class ThreadSafetyBasics
{
class UnsafeCounter
{
private int count = 0;
public void Increment()
{
count++;
}
public int Count => count;
}
class SafeCounter
{
private int count = 0;
private readonly object lockObj = new object();
public void Increment()
{
lock (lockObj)
{
count++;
}
}
public int Count
{
get
{
lock (lockObj)
{
return count;
}
}
}
}
class InterlockedCounter
{
private int count = 0;
public void Increment()
{
Interlocked.Increment(ref count);
}
public int Count => count;
}
static void Main()
{
TestUnsafeCounter();
TestSafeCounter();
TestInterlockedCounter();
}
static void TestUnsafeCounter()
{
Console.WriteLine("--- 非线程安全计数器测试 ---");
var counter = new UnsafeCounter();
Parallel.For(0, 100000, i =>
{
counter.Increment();
});
Console.WriteLine("期望值: 100000, 实际值: {0}", counter.Count);
Console.WriteLine("数据竞争导致结果不正确\n");
}
static void TestSafeCounter()
{
Console.WriteLine("--- 线程安全计数器测试(使用lock)---");
var counter = new SafeCounter();
Parallel.For(0, 100000, i =>
{
counter.Increment();
});
Console.WriteLine("期望值: 100000, 实际值: {0}", counter.Count);
}
static void TestInterlockedCounter()
{
Console.WriteLine("\n--- 线程安全计数器测试(使用Interlocked)---");
var counter = new InterlockedCounter();
Parallel.For(0, 100000, i =>
{
counter.Increment();
});
Console.WriteLine("期望值: 100000, 实际值: {0}", counter.Count);
}
}
1.2 线程安全的级别
using System;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
class ThreadSafetyLevels
{
static void Main()
{
ImmutableExample();
StatelessExample();
ThreadConfinementExample();
SynchronizedAccessExample();
}
public class ImmutablePoint
{
public int X {
get;
private set;
}
public int Y {
get;
private set;
}
public ImmutablePoint(int x, int y)
{
X = x;
Y = y;
}
public ImmutablePoint Move(int dx, int dy)
{
return new ImmutablePoint(X + dx, Y + dy);
}
}
static void ImmutableExample()
{
Console.WriteLine("--- 不可变对象(完全线程安全)---");
var point = new ImmutablePoint(0, 0);
Parallel.For(0, 10, i =>
{
var newPoint = point.Move(i, i);
Console.WriteLine("线程{0}: 新位置 ({1}, {2})",
Thread.CurrentThread.ManagedThreadId, newPoint.X, newPoint.Y);
});
}
public class StatelessCalculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Multiply(int a, int b)
{
return a * b;
}
}
static void StatelessExample()
{
Console.WriteLine("\n--- 无状态对象(线程安全)---");
var calculator = new StatelessCalculator();
Parallel.For(0, 10, i =>
{
var result = calculator.Add(i, i * 2);
Console.WriteLine("线程计算: {0} + {1} = {2}", i, i * 2, result);
});
}
static void ThreadConfinementExample()
{
Console.WriteLine("\n--- 线程封闭 ---");
ThreadLocal<List<
int>
> threadLocalList =
new ThreadLocal<List<
int>
>(() =>
new List<
int>());
Parallel.For(0, 10, i =>
{
threadLocalList.Value.Add(i);
threadLocalList.Value.Add(i * 2);
Console.WriteLine("线程{0}的列表: [{1}]",
Thread.CurrentThread.ManagedThreadId,
string.Join(", ", threadLocalList.Value));
});
threadLocalList.Dispose();
}
static void SynchronizedAccessExample()
{
Console.WriteLine("\n--- 同步访问 ---");
var sharedList = new List<
int>();
var syncRoot = new object();
Parallel.For(0, 100, i =>
{
lock (syncRoot)
{
sharedList.Add(i);
}
});
Console.WriteLine("同步列表大小: " + sharedList.Count);
}
}
二、锁机制详解
2.1 各种锁的比较与使用
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
class LockMechanisms
{
static void Main()
{
LockComparison();
RecursiveLockExample();
UpgradeableLockExample();
}
static void LockComparison()
{
Console.WriteLine("--- 不同锁机制的性能比较 ---");
const int iterations = 10000000;
int counter = 0;
Stopwatch sw = new Stopwatch();
object lockObj = new object();
counter = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
lock (lockObj)
{
counter++;
}
});
sw.Stop();
Console.WriteLine("lock语句: {0}ms, 结果: {1}",
sw.ElapsedMilliseconds, counter);
counter = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
bool taken = false;
try
{
Monitor.Enter(lockObj, ref taken);
counter++;
}
finally
{
if (taken) Monitor.Exit(lockObj);
}
});
sw.Stop();
Console.WriteLine("Monitor类: {0}ms, 结果: {1}",
sw.ElapsedMilliseconds, counter);
SpinLock spinLock = new SpinLock();
counter = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
bool lockTaken = false;
try
{
spinLock.Enter(ref lockTaken);
counter++;
}
finally
{
if (lockTaken) spinLock.Exit();
}
});
sw.Stop();
Console.WriteLine("SpinLock: {0}ms, 结果: {1}",
sw.ElapsedMilliseconds, counter);
counter = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
Interlocked.Increment(ref counter);
});
sw.Stop();
Console.WriteLine("Interlocked: {0}ms, 结果: {1}",
sw.ElapsedMilliseconds, counter);
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
counter = 0;
sw.Restart();
Parallel.For(0, iterations, i =>
{
rwLock.EnterWriteLock();
try
{
counter++;
}
finally
{
rwLock.ExitWriteLock();
}
});
sw.Stop();
Console.WriteLine("ReaderWriterLockSlim: {0}ms, 结果: {1}",
sw.ElapsedMilliseconds, counter);
rwLock.Dispose();
}
static void RecursiveLockExample()
{
Console.WriteLine("\n--- 递归锁示例 ---");
ReaderWriterLockSlim recursiveLock =
new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
void RecursiveMethod(int depth)
{
recursiveLock.EnterWriteLock();
try
{
Console.WriteLine("递归深度: {0}, 线程: {1}",
depth, Thread.CurrentThread.ManagedThreadId);
if (depth >
0)
{
RecursiveMethod(depth - 1);
}
}
finally
{
recursiveLock.ExitWriteLock();
}
}
RecursiveMethod(3);
recursiveLock.Dispose();
}
static void UpgradeableLockExample()
{
Console.WriteLine("\n--- 可升级锁示例 ---");
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
Dictionary<
int, string> cache = new Dictionary<
int, string>();
string GetOrAdd(int key, Func<
string> valueFactory)
{
rwLock.EnterUpgradeableReadLock();
try
{
if (cache.ContainsKey(key))
{
return cache[key];
}
rwLock.EnterWriteLock();
try
{
if (!cache.ContainsKey(key))
{
cache[key] = valueFactory();
}
return cache[key];
}
finally
{
rwLock.ExitWriteLock();
}
}
finally
{
rwLock.ExitUpgradeableReadLock();
}
}
Parallel.For(0, 10, i =>
{
string value = GetOrAdd(i % 3, () =>
"Value_" + i);
Console.WriteLine("键 {0}: {1}", i % 3, value);
});
rwLock.Dispose();
}
}
2.2 自定义锁和同步原语
using System;
using System.Threading;
class CustomSynchronization
{
public class SimpleSpinLock
{
private volatile int locked = 0;
public void Enter()
{
while (Interlocked.CompareExchange(ref locked, 1, 0) != 0)
{
Thread.SpinWait(1);
}
}
public void Exit()
{
Volatile.Write(ref locked, 0);
}
}
public class SimpleReaderWriterLock
{
private int readers = 0;
private int writers = 0;
private int writeRequests = 0;
private readonly object lockObj = new object();
public void EnterReadLock()
{
lock (lockObj)
{
while (writers >
0 || writeRequests >
0)
{
Monitor.Wait(lockObj);
}
readers++;
}
}
public void ExitReadLock()
{
lock (lockObj)
{
readers--;
if (readers == 0)
{
Monitor.PulseAll(lockObj);
}
}
}
public void EnterWriteLock()
{
lock (lockObj)
{
writeRequests++;
while (readers >
0 || writers >
0)
{
Monitor.Wait(lockObj);
}
writeRequests--;
writers++;
}
}
public void ExitWriteLock()
{
lock (lockObj)
{
writers--;
Monitor.PulseAll(lockObj);
}
}
}
public class SimpleSemaphore
{
private int count;
private readonly object lockObj = new object();
public SimpleSemaphore(int initialCount)
{
count = initialCount;
}
public void Wait()
{
lock (lockObj)
{
while (count == 0)
{
Monitor.Wait(lockObj);
}
count--;
}
}
public void Release()
{
lock (lockObj)
{
count++;
Monitor.Pulse(lockObj);
}
}
}
static void Main()
{
TestCustomSpinLock();
TestCustomReaderWriterLock();
TestCustomSemaphore();
}
static void TestCustomSpinLock()
{
Console.WriteLine("--- 自定义自旋锁测试 ---");
var spinLock = new SimpleSpinLock();
int counter = 0;
Parallel.For(0, 10000, i =>
{
spinLock.Enter();
counter++;
spinLock.Exit();
});
Console.WriteLine("计数器值: " + counter);
}
static void TestCustomReaderWriterLock()
{
Console.WriteLine("\n--- 自定义读写锁测试 ---");
var rwLock = new SimpleReaderWriterLock();
var data = 0;
for (int i = 0; i <
3; i++)
{
int readerId = i;
new Thread(() =>
{
for (int j = 0; j <
3; j++)
{
rwLock.EnterReadLock();
Console.WriteLine("读者{0}: 读取值 = {1}", readerId, data);
Thread.Sleep(100);
rwLock.ExitReadLock();
}
}).Start();
}
new Thread(() =>
{
for (int j = 0; j <
3; j++)
{
rwLock.EnterWriteLock();
data++;
Console.WriteLine("写者: 写入值 = " + data);
Thread.Sleep(200);
rwLock.ExitWriteLock();
}
}).Start();
Thread.Sleep(2000);
}
static void TestCustomSemaphore()
{
Console.WriteLine("\n--- 自定义信号量测试 ---");
var semaphore = new SimpleSemaphore(2);
for (int i = 0; i <
5; i++)
{
int threadId = i;
new Thread(() =>
{
Console.WriteLine("线程{0}: 等待进入", threadId);
semaphore.Wait();
Console.WriteLine("线程{0}: 进入临界区", threadId);
Thread.Sleep(1000);
Console.WriteLine("线程{0}: 离开临界区", threadId);
semaphore.Release();
}).Start();
}
Thread.Sleep(4000);
}
}
三、原子操作与内存屏障
3.1 Interlocked类的完整使用
using System;
using System.Threading;
using System.Threading.Tasks;
class InterlockedOperations
{
static void Main()
{
BasicInterlockedOperations();
InterlockedExchangeExample();
InterlockedCompareExchangeExample();
CustomSpinLockWithInterlocked();
}
static void BasicInterlockedOperations()
{
Console.WriteLine("--- Interlocked基本操作 ---");
int counter = 0;
long bigCounter = 0;
double doubleValue = 0.0;
Parallel.For(0, 100000, i =>
{
Interlocked.Increment(ref counter);
if (i % 2 == 0)
Interlocked.Decrement(ref counter);
Interlocked.Add(ref counter, 5);
Interlocked.Increment(ref bigCounter);
double newValue = i * 1.5;
double oldValue = Interlocked.Exchange(ref doubleValue, newValue);
});
Console.WriteLine("最终计数器值: " + counter);
Console.WriteLine("64位计数器值: " + bigCounter);
}
static void InterlockedExchangeExample()
{
Console.WriteLine("\n--- Interlocked.Exchange示例 ---");
object currentObject = "初始值";
string result = null;
Parallel.For(0, 10, i =>
{
object newObject = "线程" + i + "的值";
object oldObject = Interlocked.Exchange(ref currentObject, newObject);
Console.WriteLine("线程{0}: 旧值={1}, 新值={2}",
i, oldObject, newObject);
});
Console.WriteLine("最终值: " + currentObject);
}
static void InterlockedCompareExchangeExample()
{
Console.WriteLine("\n--- Interlocked.CompareExchange示例 ---");
int sharedValue = 100;
Parallel.For(0, 10, i =>
{
int localCopy, newValue;
do
{
localCopy = sharedValue;
newValue = localCopy + i;
} while (Interlocked.CompareExchange(
ref sharedValue, newValue, localCopy) != localCopy);
Console.WriteLine("线程{0}: 成功更新为 {1}", i, newValue);
});
Console.WriteLine("最终值: " + sharedValue);
}
static void CustomSpinLockWithInterlocked()
{
Console.WriteLine("\n--- 使用Interlocked实现自旋锁 ---");
int lockFlag = 0;
int sharedCounter = 0;
void EnterLock()
{
while (Interlocked.CompareExchange(ref lockFlag, 1, 0) != 0)
{
Thread.SpinWait(1);
}
}
void ExitLock()
{
Interlocked.Exchange(ref lockFlag, 0);
}
Parallel.For(0, 10000, i =>
{
EnterLock();
sharedCounter++;
ExitLock();
});
Console.WriteLine("共享计数器: " + sharedCounter);
}
}
3.2 内存屏障和Volatile
using System;
using System.Threading;
using System.Threading.Tasks;
class MemoryBarrierAndVolatile
{
static void Main()
{
VolatileExample();
MemoryBarrierExample();
LazyInitializationPattern();
}
class VolatileTest
{
private volatile bool flag = false;
private int value = 0;
public void Writer()
{
value = 42;
flag = true;
}
public void Reader()
{
if (flag)
{
Console.WriteLine("Value = " + value);
}
}
}
static void VolatileExample()
{
Console.WriteLine("--- Volatile关键字示例 ---");
var test = new VolatileTest();
Task writer = Task.Factory.StartNew(() => test.Writer());
Task reader = Task.Factory.StartNew(() =>
{
Thread.Sleep(10);
test.Reader();
});
Task.WaitAll(writer, reader);
}
static void MemoryBarrierExample()
{
Console.WriteLine("\n--- 内存屏障示例 ---");
bool flag = false;
int value = 0;
Task writer = Task.Factory.StartNew(() =>
{
value = 42;
Thread.MemoryBarrier();
flag = true;
});
Task reader = Task.Factory.StartNew(() =>
{
Thread.Sleep(10);
if (flag)
{
Thread.MemoryBarrier();
Console.WriteLine("通过内存屏障读取: " + value);
}
});
Task.WaitAll(writer, reader);
VolatileClassExample();
}
static void VolatileClassExample()
{
Console.WriteLine("\n--- Volatile类示例 ---");
int sharedValue = 0;
Task writer = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
Volatile.Write(ref sharedValue, i);
Thread.Sleep(100);
}
});
Task reader = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
int value = Volatile.Read(ref sharedValue);
Console.WriteLine("读取值: " + value);
Thread.Sleep(100);
}
});
Task.WaitAll(writer, reader);
}
class Singleton
{
private static volatile Singleton instance;
private static readonly object lockObj = new object();
private Singleton() {
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
static void LazyInitializationPattern()
{
Console.WriteLine("\n--- 延迟初始化模式 ---");
Parallel.For(0, 10, i =>
{
var singleton = Singleton.Instance;
Console.WriteLine("线程{0}: 获得单例 {1}",
i, singleton.GetHashCode());
});
}
}
四、死锁的预防与检测
4.1 死锁的产生与预防
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class DeadlockPreventionAndDetection
{
static void Main()
{
DeadlockPreventionByOrdering();
DeadlockPreventionByTimeout();
DeadlockDetection();
}
static void DeadlockExample()
{
Console.WriteLine("--- 死锁示例(会卡住)---");
object lock1 = new object();
object lock2 = new object();
Task task1 = Task.Factory.StartNew(() =>
{
lock (lock1)
{
Console.WriteLine("Task1: 获得lock1");
Thread.Sleep(100);
lock (lock2)
{
Console.WriteLine("Task1: 获得lock2");
}
}
});
Task task2 = Task.Factory.StartNew(() =>
{
lock (lock2)
{
Console.WriteLine("Task2: 获得lock2");
Thread.Sleep(100);
lock (lock1)
{
Console.WriteLine("Task2: 获得lock1");
}
}
});
Task.WaitAll(task1, task2);
}
static void DeadlockPreventionByOrdering()
{
Console.WriteLine("--- 通过锁顺序预防死锁 ---");
object lock1 = new object();
object lock2 = new object();
var lockOrder = new Dictionary<
object, int>
{
{ lock1, 1
},
{ lock2, 2
}
};
void AcquireLocksInOrder(object firstLock, object secondLock)
{
object first, second;
if (lockOrder[firstLock] < lockOrder[secondLock])
{
first = firstLock;
second = secondLock;
}
else
{
first = secondLock;
second = firstLock;
}
lock (first)
{
Console.WriteLine("线程{0}: 获得第一个锁",
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(50);
lock (second)
{
Console.WriteLine("线程{0}: 获得第二个锁",
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(50);
}
}
}
Task task1 = Task.Factory.StartNew(() =>
AcquireLocksInOrder(lock1, lock2));
Task task2 = Task.Factory.StartNew(() =>
AcquireLocksInOrder(lock2, lock1));
Task.WaitAll(task1, task2);
Console.WriteLine("成功避免死锁!\n");
}
static void DeadlockPreventionByTimeout()
{
Console.WriteLine("--- 通过超时预防死锁 ---");
object lock1 = new object();
object lock2 = new object();
void TryAcquireWithTimeout(object firstLock, object secondLock, int taskId)
{
bool acquired1 = false;
bool acquired2 = false;
try
{
Monitor.TryEnter(firstLock, TimeSpan.FromSeconds(1), ref acquired1);
if (!acquired1)
{
Console.WriteLine("Task{0}: 获取第一个锁超时", taskId);
return;
}
Console.WriteLine("Task{0}: 获得第一个锁", taskId);
Thread.Sleep(100);
Monitor.TryEnter(secondLock, TimeSpan.FromSeconds(1), ref acquired2);
if (!acquired2)
{
Console.WriteLine("Task{0}: 获取第二个锁超时", taskId);
return;
}
Console.WriteLine("Task{0}: 获得第二个锁", taskId);
Thread.Sleep(50);
}
finally
{
if (acquired2) Monitor.Exit(secondLock);
if (acquired1) Monitor.Exit(firstLock);
}
}
Task task1 = Task.Factory.StartNew(() =>
TryAcquireWithTimeout(lock1, lock2, 1));
Task task2 = Task.Factory.StartNew(() =>
TryAcquireWithTimeout(lock2, lock1, 2));
Task.WaitAll(task1, task2);
}
class DeadlockDetector
{
private Dictionary<Thread, List<
object>
> threadLocks =
new Dictionary<Thread, List<
object>
>();
private Dictionary<
object, Thread> lockOwners =
new Dictionary<
object, Thread>();
private readonly object detectorLock = new object();
public bool TryAcquireLock(object lockObj)
{
lock (detectorLock)
{
Thread currentThread = Thread.CurrentThread;
if (lockOwners.ContainsKey(lockObj))
{
Thread owner = lockOwners[lockObj];
if (WouldCauseDeadlock(currentThread, owner))
{
Console.WriteLine("检测到潜在死锁!");
return false;
}
}
if (!threadLocks.ContainsKey(currentThread))
{
threadLocks[currentThread] = new List<
object>();
}
threadLocks[currentThread].Add(lockObj);
lockOwners[lockObj] = currentThread;
return true;
}
}
public void ReleaseLock(object lockObj)
{
lock (detectorLock)
{
Thread currentThread = Thread.CurrentThread;
if (threadLocks.ContainsKey(currentThread))
{
threadLocks[currentThread].Remove(lockObj);
}
if (lockOwners.ContainsKey(lockObj))
{
lockOwners.Remove(lockObj);
}
}
}
private bool WouldCauseDeadlock(Thread requester, Thread owner)
{
if (threadLocks.ContainsKey(requester))
{
foreach (var lockObj in threadLocks[requester])
{
if (lockOwners.ContainsKey(lockObj) &&
lockOwners[lockObj] == owner)
{
return true;
}
}
}
return false;
}
}
static void DeadlockDetection()
{
Console.WriteLine("\n--- 死锁检测示例 ---");
DeadlockDetector detector = new DeadlockDetector();
object lock1 = new object();
object lock2 = new object();
Task task1 = Task.Factory.StartNew(() =>
{
if (detector.TryAcquireLock(lock1))
{
Console.WriteLine("Task1: 获得lock1");
Thread.Sleep(100);
if (detector.TryAcquireLock(lock2))
{
Console.WriteLine("Task1: 获得lock2");
detector.ReleaseLock(lock2);
}
detector.ReleaseLock(lock1);
}
});
Task task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(50);
if (detector.TryAcquireLock(lock2))
{
Console.WriteLine("Task2: 获得lock2");
Thread.Sleep(100);
if (detector.TryAcquireLock(lock1))
{
Console.WriteLine("Task2: 获得lock1");
detector.ReleaseLock(lock1);
}
detector.ReleaseLock(lock2);
}
});
Task.WaitAll(task1, task2);
}
}
五、竞态条件与解决方案
5.1 常见竞态条件
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class RaceConditions
{
static void Main()
{
CheckThenActRaceCondition();
ReadModifyWriteRaceCondition();
LazyInitializationRaceCondition();
CollectionRaceCondition();
}
static void CheckThenActRaceCondition()
{
Console.WriteLine("--- Check-Then-Act竞态条件 ---");
class UnsafeCounter
{
private int count = 0;
private int maxCount = 100;
public bool IncrementIfPossible()
{
if (count < maxCount)
{
Thread.Sleep(0);
count++;
return true;
}
return false;
}
public int Count => count;
}
class SafeCounter
{
private int count = 0;
private int maxCount = 100;
private readonly object lockObj = new object();
public bool IncrementIfPossible()
{
lock (lockObj)
{
if (count < maxCount)
{
count++;
return true;
}
return false;
}
}
public int Count
{
get {
lock (lockObj) {
return count;
}
}
}
}
var unsafeCounter = new UnsafeCounter();
Parallel.For(0, 200, i =>
{
unsafeCounter.IncrementIfPossible();
});
Console.WriteLine("不安全计数器: {0} (可能超过100)", unsafeCounter.Count);
var safeCounter = new SafeCounter();
Parallel.For(0, 200, i =>
{
safeCounter.IncrementIfPossible();
});
Console.WriteLine("安全计数器: {0} (不会超过100)", safeCounter.Count);
}
static void ReadModifyWriteRaceCondition()
{
Console.WriteLine("\n--- Read-Modify-Write竞态条件 ---");
int unsafeValue = 0;
int safeValue = 0;
Parallel.For(0, 100000, i =>
{
unsafeValue = unsafeValue + 1;
});
Parallel.For(0, 100000, i =>
{
Interlocked.Increment(ref safeValue);
});
Console.WriteLine("不安全值: {0} (预期: 100000)", unsafeValue);
Console.WriteLine("安全值: {0} (预期: 100000)", safeValue);
}
static void LazyInitializationRaceCondition()
{
Console.WriteLine("\n--- 延迟初始化竞态条件 ---");
class UnsafeLazy
{
private ExpensiveObject instance;
public ExpensiveObject Instance
{
get
{
if (instance == null)
{
instance = new ExpensiveObject();
}
return instance;
}
}
}
class SafeLazy
{
private readonly Lazy<ExpensiveObject> lazyInstance =
new Lazy<ExpensiveObject>(() =>
new ExpensiveObject());
public ExpensiveObject Instance => lazyInstance.Value;
}
class ExpensiveObject
{
private static int instanceCount = 0;
public int Id {
get;
}
public ExpensiveObject()
{
Id = Interlocked.Increment(ref instanceCount);
Console.WriteLine("创建实例 #{0}", Id);
}
}
var unsafeLazy = new UnsafeLazy();
Parallel.For(0, 10, i =>
{
var obj = unsafeLazy.Instance;
});
var safeLazy = new SafeLazy();
Parallel.For(0, 10, i =>
{
var obj = safeLazy.Instance;
});
}
static void CollectionRaceCondition()
{
Console.WriteLine("\n--- 集合竞态条件 ---");
var unsafeList = new List<
int>();
var exceptions = 0;
Parallel.For(0, 1000, i =>
{
try
{
unsafeList.Add(i);
}
catch
{
Interlocked.Increment(ref exceptions);
}
});
Console.WriteLine("不安全列表: 大小={0}, 异常={1}",
unsafeList.Count, exceptions);
var safeList = new System.Collections.Concurrent.ConcurrentBag<
int>();
Parallel.For(0, 1000, i =>
{
safeList.Add(i);
});
Console.WriteLine("安全列表: 大小={0}", safeList.Count);
}
}
六、线程安全集合与模式
6.1 线程安全包装器
using System;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
class ThreadSafeWrappers
{
public class ThreadSafeDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> dictionary =
new Dictionary<TKey, TValue>();
private readonly ReaderWriterLockSlim rwLock =
new ReaderWriterLockSlim();
public void Add(TKey key, TValue value)
{
rwLock.EnterWriteLock();
try
{
dictionary.Add(key, value);
}
finally
{
rwLock.ExitWriteLock();
}
}
public bool TryGetValue(TKey key, out TValue value)
{
rwLock.EnterReadLock();
try
{
return dictionary.TryGetValue(key, out value);
}
finally
{
rwLock.ExitReadLock();
}
}
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
rwLock.EnterUpgradeableReadLock();
try
{
TValue value;
if (dictionary.TryGetValue(key, out value))
{
return value;
}
rwLock.EnterWriteLock();
try
{
if (!dictionary.TryGetValue(key, out value))
{
value = valueFactory(key);
dictionary.Add(key, value);
}
return value;
}
finally
{
rwLock.ExitWriteLock();
}
}
finally
{
rwLock.ExitUpgradeableReadLock();
}
}
public void Clear()
{
rwLock.EnterWriteLock();
try
{
dictionary.Clear();
}
finally
{
rwLock.ExitWriteLock();
}
}
public int Count
{
get
{
rwLock.EnterReadLock();
try
{
return dictionary.Count;
}
finally
{
rwLock.ExitReadLock();
}
}
}
~ThreadSafeDictionary()
{
rwLock?.Dispose();
}
}
public class ThreadSafeEvent<T>
{
private event Action<T> handlers;
private readonly object lockObj = new object();
public void Subscribe(Action<T> handler)
{
lock (lockObj)
{
handlers += handler;
}
}
public void Unsubscribe(Action<T> handler)
{
lock (lockObj)
{
handlers -= handler;
}
}
public void Raise(T args)
{
Action<T> localHandlers;
lock (lockObj)
{
localHandlers = handlers;
}
localHandlers?.Invoke(args);
}
}
static void Main()
{
TestThreadSafeDictionary();
TestThreadSafeEvent();
}
static void TestThreadSafeDictionary()
{
Console.WriteLine("--- 线程安全字典测试 ---");
var dict = new ThreadSafeDictionary<
int, string>();
Parallel.For(0, 100, i =>
{
dict.Add(i, "Value_" + i);
});
Console.WriteLine("字典大小: " + dict.Count);
Parallel.For(0, 100, i =>
{
string value;
if (dict.TryGetValue(i, out value))
{
if (i % 10 == 0)
{
Console.WriteLine("键{0}: {1}", i, value);
}
}
});
Parallel.For(100, 110, i =>
{
string value = dict.GetOrAdd(i, key =>
"Generated_" + key);
Console.WriteLine("GetOrAdd({0}): {1}", i, value);
});
}
static void TestThreadSafeEvent()
{
Console.WriteLine("\n--- 线程安全事件测试 ---");
var safeEvent = new ThreadSafeEvent<
string>();
Parallel.For(0, 5, i =>
{
safeEvent.Subscribe(msg =>
Console.WriteLine("处理器{0}: {1}", i, msg));
});
Parallel.For(0, 3, i =>
{
safeEvent.Raise("消息_" + i);
});
}
}
6.2 Copy-On-Write模式
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
class CopyOnWritePattern
{
public class CopyOnWriteList<T>
{
private volatile T[] array = new T[0];
private readonly object writeLock = new object();
public void Add(T item)
{
lock (writeLock)
{
T[] newArray = new T[array.Length + 1];
Array.Copy(array, newArray, array.Length);
newArray[array.Length] = item;
array = newArray;
}
}
public bool Remove(T item)
{
lock (writeLock)
{
int index = Array.IndexOf(array, item);
if (index <
0)
return false;
T[] newArray = new T[array.Length - 1];
if (index >
0)
Array.Copy(array, 0, newArray, 0, index);
if (index < array.Length - 1)
Array.Copy(array, index + 1, newArray, index,
array.Length - index - 1);
array = newArray;
return true;
}
}
public T this[int index]
{
get
{
T[] localArray = array;
return localArray[index];
}
}
public int Count
{
get {
return array.Length;
}
}
public IEnumerator<T> GetEnumerator()
{
T[] localArray = array;
foreach (T item in localArray)
{
yield return item;
}
}
}
static void Main()
{
Console.WriteLine("--- Copy-On-Write模式 ---");
var cowList = new CopyOnWriteList<
int>();
Task writer = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
10; i++)
{
cowList.Add(i);
Console.WriteLine("添加: " + i);
Thread.Sleep(100);
}
});
Task[] readers = new Task[3];
for (int r = 0; r < readers.Length; r++)
{
int readerId = r;
readers[r] = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
5; i++)
{
Thread.Sleep(250);
Console.WriteLine("读者{0}: 当前列表大小 = {1}",
readerId, cowList.Count);
foreach (var item in cowList)
{
}
}
});
}
Task.WaitAll(writer);
Task.WaitAll(readers);
Console.WriteLine("最终列表大小: " + cowList.Count);
}
}
七、异常处理与资源保护
7.1 线程异常处理
using System;
using System.Threading;
using System.Threading.Tasks;
class ThreadExceptionHandling
{
static void Main()
{
HandleThreadExceptions();
HandleTaskExceptions();
HandleAggregateExceptions();
UnobservedTaskExceptions();
}
static void HandleThreadExceptions()
{
Console.WriteLine("--- Thread异常处理 ---");
Thread thread = new Thread(() =>
{
try
{
throw new InvalidOperationException("线程异常");
}
catch (Exception ex)
{
Console.WriteLine("捕获线程异常: " + ex.Message);
}
});
thread.Start();
thread.Join();
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
Console.WriteLine("未处理异常: " + e.ExceptionObject);
};
}
static void HandleTaskExceptions()
{
Console.WriteLine("\n--- Task异常处理 ---");
Task faultedTask = Task.Factory.StartNew(() =>
{
throw new InvalidOperationException("Task异常");
});
try
{
faultedTask.Wait();
}
catch (AggregateException ae)
{
foreach (var ex in ae.InnerExceptions)
{
Console.WriteLine("Task异常: " + ex.Message);
}
}
Task.Factory.StartNew(() =>
{
throw new Exception("另一个Task异常");
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
Console.WriteLine("通过ContinueWith处理: " +
t.Exception.InnerException.Message);
}
});
Thread.Sleep(100);
}
static void HandleAggregateExceptions()
{
Console.WriteLine("\n--- AggregateException处理 ---");
Task[] tasks = new Task[]
{
Task.Factory.StartNew(() =>
{
throw new ArgumentException("参数错误");
}),
Task.Factory.StartNew(() =>
{
throw new InvalidOperationException("操作无效");
}),
Task.Factory.StartNew(() =>
{
throw new NullReferenceException("空引用");
})
};
try
{
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
ae.Handle(ex =>
{
if (ex is ArgumentException)
{
Console.WriteLine("处理ArgumentException: " + ex.Message);
return true;
}
else if (ex is InvalidOperationException)
{
Console.WriteLine("处理InvalidOperationException: " + ex.Message);
return true;
}
return false;
});
}
}
static void UnobservedTaskExceptions()
{
Console.WriteLine("\n--- 未观察的Task异常 ---");
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
Console.WriteLine("未观察的异常: " + e.Exception.Message);
e.SetObserved();
};
Task.Factory.StartNew(() =>
{
throw new Exception("未观察的异常");
});
Thread.Sleep(100);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Thread.Sleep(100);
}
}
7.2 资源清理与保护
using System;
using System.Threading;
using System.Threading.Tasks;
class ResourceProtection
{
class LockGuard
: IDisposable
{
private readonly object lockObj;
private bool isLocked;
public LockGuard(object lockObj)
{
this.lockObj = lockObj;
Monitor.Enter(lockObj, ref isLocked);
}
public void Dispose()
{
if (isLocked)
{
Monitor.Exit(lockObj);
isLocked = false;
}
}
}
class ThreadSafeResourceManager
: IDisposable
{
private readonly ReaderWriterLockSlim rwLock =
new ReaderWriterLockSlim();
private Dictionary<
int, IDisposable> resources =
new Dictionary<
int, IDisposable>();
private volatile bool disposed = false;
public void AddResource(int id, IDisposable resource)
{
ThrowIfDisposed();
rwLock.EnterWriteLock();
try
{
if (resources.ContainsKey(id))
{
resources[id]?.Dispose();
}
resources[id] = resource;
}
finally
{
rwLock.ExitWriteLock();
}
}
public T GetResource<T>(int id) where T : class,
IDisposable
{
ThrowIfDisposed();
rwLock.EnterReadLock();
try
{
IDisposable resource;
if (resources.TryGetValue(id, out resource))
{
return resource as T;
}
return null;
}
finally
{
rwLock.ExitReadLock();
}
}
private void ThrowIfDisposed()
{
if (disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
rwLock.EnterWriteLock();
try
{
foreach (var resource in resources.Values)
{
resource?.Dispose();
}
resources.Clear();
}
finally
{
rwLock.ExitWriteLock();
}
rwLock?.Dispose();
}
disposed = true;
}
}
~ThreadSafeResourceManager()
{
Dispose(false);
}
}
class ResourcePool<T>
where T : class,
new()
{
private readonly ConcurrentBag<T> pool = new ConcurrentBag<T>();
private readonly SemaphoreSlim semaphore;
private readonly int maxSize;
public ResourcePool(int maxSize)
{
this.maxSize = maxSize;
this.semaphore = new SemaphoreSlim(maxSize, maxSize);
}
public async Task<ResourceHandle<T>
> AcquireAsync(
TimeSpan timeout)
{
if (!await semaphore.WaitAsync(timeout))
{
throw new TimeoutException("获取资源超时");
}
T resource;
if (!pool.TryTake(out resource))
{
resource = new T();
}
return new ResourceHandle<T>(resource, this);
}
private void Release(T resource)
{
pool.Add(resource);
semaphore.Release();
}
public class ResourceHandle<TResource>
: IDisposable
where TResource : class
{
private TResource resource;
private ResourcePool<TResource> pool;
public ResourceHandle(TResource resource,
ResourcePool<TResource> pool)
{
this.resource = resource;
this.pool = pool;
}
public TResource Resource => resource;
public void Dispose()
{
if (resource != null && pool != null)
{
pool.Release(resource);
resource = null;
pool = null;
}
}
}
}
static void Main()
{
TestLockGuard();
TestResourceManager();
TestResourcePool().Wait();
}
static void TestLockGuard()
{
Console.WriteLine("--- LockGuard测试 ---");
object lockObj = new object();
int sharedValue = 0;
Parallel.For(0, 100, i =>
{
using (new LockGuard(lockObj))
{
sharedValue++;
}
});
Console.WriteLine("共享值: " + sharedValue);
}
static void TestResourceManager()
{
Console.WriteLine("\n--- 线程安全资源管理器测试 ---");
using (var manager = new ThreadSafeResourceManager())
{
Parallel.For(0, 10, i =>
{
var resource = new System.IO.MemoryStream();
manager.AddResource(i, resource);
});
Parallel.For(0, 10, i =>
{
var resource = manager.GetResource<System.IO.MemoryStream>(i);
if (resource != null)
{
Console.WriteLine("获取资源 {0}", i);
}
});
}
Console.WriteLine("所有资源已清理");
}
static async Task TestResourcePool()
{
Console.WriteLine("\n--- 资源池测试 ---");
var pool = new ResourcePool<
object>(3);
var tasks = new Task[5];
for (int i = 0; i <
5; i++)
{
int taskId = i;
tasks[i] = Task.Run(async () =>
{
try
{
using (var handle = await pool.AcquireAsync(
TimeSpan.FromSeconds(2)))
{
Console.WriteLine("Task{0}: 获得资源", taskId);
await Task.Delay(1000);
Console.WriteLine("Task{0}: 释放资源", taskId);
}
}
catch (TimeoutException)
{
Console.WriteLine("Task{0}: 超时", taskId);
}
});
}
await Task.WhenAll(tasks);
}
}
八、性能优化与最佳实践
8.1 减少锁争用
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections.Concurrent;
class LockContentionOptimization
{
static void Main()
{
LockGranularityOptimization();
LockFreeOptimization();
PartitioningOptimization();
}
static void LockGranularityOptimization()
{
Console.WriteLine("--- 锁粒度优化 ---");
class CoarseGrainedCounter
{
private int[] counters = new int[10];
private readonly object lockObj = new object();
public void Increment(int index)
{
lock (lockObj)
{
counters[index]++;
}
}
public int GetValue(int index)
{
lock (lockObj)
{
return counters[index];
}
}
}
class FineGrainedCounter
{
private class CounterCell
{
public int Value;
public readonly object Lock = new object();
}
private CounterCell[] cells = new CounterCell[10];
public FineGrainedCounter()
{
for (int i = 0; i < cells.Length; i++)
{
cells[i] = new CounterCell();
}
}
public void Increment(int index)
{
lock (cells[index].Lock)
{
cells[index].Value++;
}
}
public int GetValue(int index)
{
lock (cells[index].Lock)
{
return cells[index].Value;
}
}
}
Stopwatch sw = new Stopwatch();
var coarse = new CoarseGrainedCounter();
sw.Start();
Parallel.For(0, 1000000, i =>
{
coarse.Increment(i % 10);
});
sw.Stop();
Console.WriteLine("粗粒度锁: {0}ms", sw.ElapsedMilliseconds);
var fine = new FineGrainedCounter();
sw.Restart();
Parallel.For(0, 1000000, i =>
{
fine.Increment(i % 10);
});
sw.Stop();
Console.WriteLine("细粒度锁: {0}ms", sw.ElapsedMilliseconds);
}
static void LockFreeOptimization()
{
Console.WriteLine("\n--- 无锁优化 ---");
class LockFreeStack<T>
{
private class Node
{
public T Value;
public Node Next;
}
private Node head;
public void Push(T item)
{
Node newNode = new Node { Value = item
};
Node currentHead;
do
{
currentHead = head;
newNode.Next = currentHead;
} while (Interlocked.CompareExchange(
ref head, newNode, currentHead) != currentHead);
}
public bool TryPop(out T result)
{
Node currentHead;
Node newHead;
do
{
currentHead = head;
if (currentHead == null)
{
result = default(T);
return false;
}
newHead = currentHead.Next;
} while (Interlocked.CompareExchange(
ref head, newHead, currentHead) != currentHead);
result = currentHead.Value;
return true;
}
}
var lockFreeStack = new LockFreeStack<
int>();
Parallel.For(0, 1000, i =>
{
lockFreeStack.Push(i);
});
int popCount = 0;
Parallel.For(0, 500, i =>
{
int value;
if (lockFreeStack.TryPop(out value))
{
Interlocked.Increment(ref popCount);
}
});
Console.WriteLine("成功弹出: " + popCount);
}
static void PartitioningOptimization()
{
Console.WriteLine("\n--- 分区优化 ---");
class PartitionedCounter
{
private ThreadLocal<
int> localCounters =
new ThreadLocal<
int>(() =>
0);
private int globalCounter = 0;
public void Increment()
{
localCounters.Value++;
if (localCounters.Value % 100 == 0)
{
Interlocked.Add(ref globalCounter, 100);
localCounters.Value = 0;
}
}
public int GetTotal()
{
int total = globalCounter;
foreach (var value in localCounters.Values)
{
total += value;
}
return total;
}
}
var partitioned = new PartitionedCounter();
Stopwatch sw = new Stopwatch();
sw.Start();
Parallel.For(0, 1000000, i =>
{
partitioned.Increment();
});
sw.Stop();
Console.WriteLine("分区计数器: 值={0}, 时间={1}ms",
partitioned.GetTotal(), sw.ElapsedMilliseconds);
}
}
8.2 避免False Sharing
using System;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
class FalseSharingPrevention
{
[StructLayout(LayoutKind.Sequential)]
struct BadCounters
{
public int Counter1;
public int Counter2;
}
[StructLayout(LayoutKind.Sequential)]
struct GoodCounters
{
public int Counter1;
private fixed byte padding1[60];
public int Counter2;
private fixed byte padding2[60];
}
static void Main()
{
Console.WriteLine("--- False Sharing性能影响 ---");
TestBadCounters();
TestGoodCounters();
}
static unsafe void TestBadCounters()
{
BadCounters counters = new BadCounters();
Stopwatch sw = new Stopwatch();
sw.Start();
Task t1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
100000000; i++)
{
counters.Counter1++;
}
});
Task t2 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
100000000; i++)
{
counters.Counter2++;
}
});
Task.WaitAll(t1, t2);
sw.Stop();
Console.WriteLine("有False Sharing: {0}ms", sw.ElapsedMilliseconds);
}
static unsafe void TestGoodCounters()
{
GoodCounters counters = new GoodCounters();
Stopwatch sw = new Stopwatch();
sw.Start();
Task t1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
100000000; i++)
{
counters.Counter1++;
}
});
Task t2 = Task.Factory.StartNew(() =>
{
for (int i = 0; i <
100000000; i++)
{
counters.Counter2++;
}
});
Task.WaitAll(t1, t2);
sw.Stop();
Console.WriteLine("无False Sharing: {0}ms", sw.ElapsedMilliseconds);
}
}
总结
线程保护核心原则
| 原则 | 说明 | 实践方法 |
|---|
| 最小化共享状态 | 减少线程间共享数据 | 使用不可变对象、ThreadLocal |
| 正确同步 | 所有共享数据访问必须同步 | 使用lock、Interlocked等 |
| 避免死锁 | 防止循环等待 | 固定锁顺序、使用超时 |
| 优化性能 | 减少锁争用 | 细粒度锁、无锁编程 |
| 异常安全 | 确保资源正确释放 | using语句、finally块 |
选择合适的保护机制
| 场景 | 推荐方案 | 原因 |
|---|
| 简单共享变量 | Interlocked | 原子操作,高性能 |
| 复杂临界区 | lock/Monitor | 简单可靠 |
| 读多写少 | ReaderWriterLockSlim | 提高并发读 |
| 短时锁定 | SpinLock | 避免上下文切换 |
| 跨进程同步 | Mutex | 系统级同步 |
| 生产者-消费者 | BlockingCollection | 内置支持 |
| 高性能场景 | 无锁算法 | 最大性能 |
关键最佳实践
- 优先使用高级抽象:ConcurrentCollections > 手动锁
- 保持锁的时间尽可能短
- 避免在锁内调用未知代码
- 使用readonly字段作为锁对象
- 总是在finally块中释放锁
- 考虑使用不可变数据结构
- 定期review多线程代码
- 进行压力测试和并发测试