在JAVA中,用synchronized关键字用于确保多个线程不会同时执行某个方法或代码块,从而防止并发问题,C#中有多中方法来处理这种情况。
Lock语句
lock语句是最常用的同步机制,类似于JAVA的synchronized。他使用一个对象作为锁,确保同一个时间只有一个线程可以进入被锁定的代码块。示例如下。
using System;
using System.Threading;
class Program
{
private static readonly object _lock = new object();
private static int _counter = 0;
static void Main()
{
Thread thread1 = new Thread(IncrementCounter);
Thread thread2 = new Thread(IncrementCounter);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
lock (_lock)
{
_counter++;
}
}
}
}
Monitor类
monitor提供了更细粒度的控制,允许手动进入临界区。lock语句实际是monitor的一个简化版本。monitor示例如下。
using System;
using System.Threading;
class Program
{
private static readonly object _lock = new object();
private static int _counter = 0;
static void Main()
{
Thread thread1 = new Thread(IncrementCounter);
Thread thread2 = new Thread(IncrementCounter);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
Monitor.Enter(_lock);
try
{
_counter++;
}
finally
{
Monitor.Exit(_lock);
}
}
}
}
Mutex类
Mutex类是一个互斥量类,是一个更重量级的一个同步机制,适用于跨进程的同步,和lock和monitor不同,mutex可以在不同进程之中共享。示例如下。
using System;
using System.Threading;
class Program
{
private static Mutex _mutex = new Mutex();
static void Main()
{
Thread thread1 = new Thread(IncrementCounter);
Thread thread2 = new Thread(IncrementCounter);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
private static int _counter = 0;
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
_mutex.WaitOne(); // 获取互斥量
try
{
_counter++;
}
finally
{
_mutex.ReleaseMutex(); // 释放互斥量
}
}
}
}
ReadWriterLockSlim
ReadWriterLockSlim提供读写锁功能,允许多个线程同时读资源,但是写入资源的时候,只允许一个线程访问,如果是在读多写入写入少的场景下是非常有用的。示例如下。
using System;
using System.Threading;
class Program
{
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static int _counter = 0;
static void Main()
{
Thread readerThread = new Thread(ReadCounter);
Thread writerThread = new Thread(IncrementCounter);
readerThread.Start();
writerThread.Start();
readerThread.Join();
writerThread.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
static void ReadCounter()
{
for (int i = 0; i < 1000; i++)
{
_lock.EnterReadLock();
try
{
Console.WriteLine($"Reading counter: {_counter}");
}
finally
{
_lock.ExitReadLock();
}
}
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
_lock.EnterWriteLock();
try
{
_counter++;
}
finally
{
_lock.ExitWriteLock();
}
}
}
}
Semaphore ,SemaphoreSlim
Semaphore 和 SemaphoreSlim 允许多个线程同时访问资源,但限制了同时访问的最大线程数。SemaphoreSlim 是 Semaphore 的轻量级版本,适合单进程内的同步。示例如下。
using System;
using System.Threading;
class Program
{
private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); // 允许最多1个线程同时访问
private static int _counter = 0;
static void Main()
{
Thread thread1 = new Thread(IncrementCounter);
Thread thread2 = new Thread(IncrementCounter);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
_semaphore.Wait(); // 等待进入临界区
try
{
_counter++;
}
finally
{
_semaphore.Release(); // 释放临界区
}
}
}
}
async,wait,semahporeSlim结合使用
如果场景有异步编程中进行同步操作,可以用以上三者结合,实现同步非阻塞的场景。示例如下。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); // 允许最多1个线程同时访问
private static int _counter = 0;
static async Task Main()
{
Task task1 = IncrementCounterAsync();
Task task2 = IncrementCounterAsync();
await Task.WhenAll(task1, task2);
Console.WriteLine($"Final counter value: {_counter}");
}
static async Task IncrementCounterAsync()
{
for (int i = 0; i < 1000; i++)
{
await _semaphore.WaitAsync(); // 等待进入临界区
try
{
_counter++;
}
finally
{
_semaphore.Release(); // 释放临界区
}
}
}
}
Interlocked
interlocked提供了一下原子操作,适用于一些简单的计数器,增量,减量的操作。比Lock还高效,原因在于他不需要创建和管理锁对象。
using System;
using System.Threading;
class Program
{
private static int _counter = 0;
static void Main()
{
Thread thread1 = new Thread(IncrementCounter);
Thread thread2 = new Thread(IncrementCounter);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final counter value: {_counter}");
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
Interlocked.Increment(ref _counter);
}
}
}
总结
lock:最常用的方式,简单易用,适用于大多数场景。
Monitor:提供了更细粒度的控制,适合需要手动管理锁的情况。
Mutex:适用于跨进程的同步。
Semaphore 和 SemaphoreSlim:允许多个线程同时访问资源,适合限制并发访问数量的场景。
ReaderWriterLockSlim:适用于读多写少的场景,允许多个线程同时读取资源。
Interlocked:提供了高效的原子操作,适合简单的计数器或增量操作。
根据你的具体需求选择合适的同步机制。如果你只是需要简单的线程安全,lock 或 Interlocked 通常是最佳选择。如果你需要更复杂的同步逻辑,可以考虑使用 Monitor、Mutex 或 ReaderWriterLockSlim。
标签:JAVA,Synchronized,Thread,C#,lock,counter,static,IncrementCounter,new
From: https://blog.csdn.net/qq_41435130/article/details/145262914