Java中的ReentrantLock是可重入的互斥锁,支持同一个线程多次获取锁而不会被阻塞,常用于多线程场景下的资源同步控制。C#作为同样支持多线程编程的语言,原生就提供了可重入锁的实现能力,不需要像Java那样单独引入特定的锁类就能实现相同的效果。

C#内置的可重入锁实现方式
1. 使用lock语句实现可重入锁
lock语句是C#中最常用的同步方式,它底层基于Monitor类实现,天然支持可重入特性。同一个线程可以多次进入lock保护的代码块,不会因为重复获取锁而导致死锁。
下面是一个lock语句实现可重入锁的示例:
using System;
using System.Threading;
class ReentrantLockDemo
{
private static readonly object lockObj = new object();
static void Main()
{
// 启动子线程执行可重入锁测试
Thread thread = new Thread(ExecuteWithReentrantLock);
thread.Start();
thread.Join();
}
static void ExecuteWithReentrantLock()
{
Console.WriteLine("线程尝试第一次获取锁");
lock (lockObj)
{
Console.WriteLine("第一次获取锁成功");
// 同一个线程再次获取锁,不会阻塞
lock (lockObj)
{
Console.WriteLine("第二次获取锁成功,可重入特性生效");
DoAnotherWork();
}
Console.WriteLine("第一次锁的作用域结束");
}
}
static void DoAnotherWork()
{
lock (lockObj)
{
Console.WriteLine("嵌套方法内获取锁成功");
}
}
}
运行上述代码可以看到,同一个线程三次获取同一个lock对象对应的锁都成功执行,不会出现阻塞,这就是可重入锁的典型表现。
2. 直接使用Monitor类实现可重入锁
lock语句本质是Monitor类的语法糖,我们也可以直接使用Monitor类的Enter和Exit方法来实现可重入锁,这种方式可以更灵活地控制锁的获取和释放逻辑。
使用Monitor类的示例代码如下:
using System;
using System.Threading;
class MonitorReentrantDemo
{
private static readonly object monitorObj = new object();
static void Main()
{
Thread worker = new Thread(ProcessWithMonitor);
worker.Start();
worker.Join();
}
static void ProcessWithMonitor()
{
// 获取锁
Monitor.Enter(monitorObj);
try
{
Console.WriteLine("Monitor第一次获取锁成功");
// 再次获取同一个锁,可重入
Monitor.Enter(monitorObj);
try
{
Console.WriteLine("Monitor第二次获取锁成功");
}
finally
{
// 释放一次锁
Monitor.Exit(monitorObj);
}
}
finally
{
// 释放剩余的锁
Monitor.Exit(monitorObj);
}
}
}
需要注意的是,使用Monitor类时,Enter的调用次数必须和Exit的调用次数一致,否则会导致锁无法正确释放,引发其他线程长时间阻塞的问题。
C#可重入锁与Java ReentrantLock的特性对比
我们可以通过下表对比C#的可重入锁实现和Java ReentrantLock的核心特性:
| 特性 | Java ReentrantLock | C# lock/Monitor |
|---|---|---|
| 可重入支持 | 支持 | 支持 |
| 公平锁支持 | 构造时可指定公平/非公平 | 不支持,默认非公平 |
| 中断响应 | 支持lockInterruptibly方法 | Monitor.TryEnter支持超时,无中断响应 |
| 条件变量 | 支持Condition | Monitor提供Wait、Pulse、PulseAll方法 |
使用注意事项
- lock语句锁定的对象必须是引用类型,不能使用值类型,否则会导致每次锁定的是装箱后的不同对象,失去同步效果。
- 锁对象的访问权限尽量设置为private static,避免外部代码意外获取锁导致死锁。
- 不要在锁保护的代码块中执行耗时过长的操作,比如IO操作、网络请求等,会降低多线程的执行效率。
- 如果需要类似Java ReentrantLock的公平锁、中断响应等高级特性,可以基于Monitor类自行封装,或者引入第三方的锁实现库。
总的来说,C#中不需要类似Java ReentrantLock的单独类,内置的lock语句和Monitor类已经完全支持可重入锁的所有基础能力,能够满足绝大多数多线程同步的开发需求。如果有特殊的高级特性要求,也可以通过扩展实现对应的功能。
C#ReentrantLock可重入锁lock语句Monitor类修改时间:2026-06-12 05:03:30