C# lock使用技巧
时间: 2025-08-09 17:37:14 浏览: 16
### C# 中 `lock` 关键字的使用技巧和最佳实践
在多线程环境中,`lock` 关键字是确保线程安全的重要工具之一。它通过创建一个互斥锁来防止多个线程同时访问共享资源,从而避免数据不一致的问题[^4]。
#### 1. 使用 `lock` 确保线程安全
`lock` 关键字用于保护共享资源,确保在同一时间只有一个线程可以访问该资源。以下是一个简单的示例,展示了如何使用 `lock` 来同步对共享变量的访问:
```csharp
private readonly object _lockObject = new object();
private int _sharedCounter = 0;
public void IncrementCounter()
{
lock (_lockObject)
{
_sharedCounter++;
}
}
```
在此示例中,`_lockObject` 是一个私有对象,专门用于锁定。通过将 `_sharedCounter` 的操作放在 `lock` 块中,可以确保同一时间只有一个线程能够修改 `_sharedCounter`[^4]。
#### 2. 避免锁定公共类型或实例
锁定的对象应该是私有的,以避免外部代码干扰锁的行为。例如,不要锁定 `this`、字符串常量或公共静态对象,因为这些对象可能被其他代码锁定,导致死锁或其他问题[^4]。
错误示例:
```csharp
public class MyClass
{
public void DangerousLock()
{
lock (this) // 不推荐:可能会被其他代码锁定
{
// 执行一些操作
}
}
}
```
正确示例:
```csharp
public class MyClass
{
private readonly object _lockObject = new object();
public void SafeLock()
{
lock (_lockObject) // 推荐:私有锁定对象
{
// 执行一些操作
}
}
}
```
#### 3. 使用双重检查锁定模式(Double-Check Locking)
在某些场景下,可以通过双重检查锁定模式减少不必要的锁竞争,提高性能。以下是一个典型的实现示例:
```csharp
private volatile IDictionary _keyTable;
public IDictionary KeyTable
{
get
{
if (_keyTable == null) // 第一次检查
{
lock (_lockObject)
{
if (_keyTable == null) // 第二次检查
{
_keyTable = new Hashtable();
}
}
}
return _keyTable;
}
}
```
在此模式中,`_keyTable` 被声明为 `volatile`,以确保多线程环境下的可见性。双重检查减少了锁的频率,提高了并发性能[^1]。
#### 4. 避免长时间持有锁
锁定的时间应尽可能短,以减少其他线程等待的时间。如果需要执行耗时操作,可以考虑将共享资源的操作分解为多个小步骤,或者使用更高级的并发机制(如 `Task Parallel Library` 或 `Concurrent Collections`)[^4]。
#### 5. 锁定不可变对象
锁定的对象应该是不可变的,以避免因对象状态改变而导致的潜在问题。例如,锁定一个 `new object()` 是安全的,因为它不会被修改[^4]。
### 示例代码:文件写入的线程安全控制
以下是一个使用 `lock` 实现线程安全的文件写入示例:
```csharp
using System;
using System.IO;
using System.Threading;
public class FileLogger
{
private readonly object _lockObject = new object();
private readonly string _filePath;
public FileLogger(string filePath)
{
_filePath = filePath;
}
public void Log(string message)
{
lock (_lockObject)
{
using (StreamWriter writer = new StreamWriter(_filePath, true))
{
writer.WriteLine($"{DateTime.Now}: {message}");
}
}
}
}
class Program
{
static void Main()
{
FileLogger logger = new FileLogger("log.txt");
Thread thread1 = new Thread(() => logger.Log("Thread 1 log entry"));
Thread thread2 = new Thread(() => logger.Log("Thread 2 log entry"));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
}
}
```
在此示例中,`Log` 方法通过 `lock` 确保了对文件的写入操作是线程安全的[^5]。
---
###
阅读全文
相关推荐




















