不能。因为struct是值类型,lock要求引用类型参数,每次装箱都会创建新对象导致锁失效,根本原因是缺乏对象身份一致性;应使用private static readonly object。

lock 能不能用在 struct 类型上?
不能。C# 编译器会直接报错:CS0185: 'lock' statement operand must be of a reference type。因为 lock 的参数必须是引用类型,而 struct 是值类型。
为什么 struct 会被拒绝?根本原因是什么
不是编译器“故意刁难”,而是语义上完全失效:
-
struct每次传给lock都会触发装箱(boxing),生成一个**新的、独立的对象实例** —— 每个线程锁的其实是不同的对象,根本起不到互斥作用; - 即使你写成
lock(myStruct),实际等价于lock((object)myStruct),每次装箱都 new 一个新object,锁对象不唯一,同步失效; - 更危险的是:这种代码看似能编译(某些旧版编译器可能静默允许,但行为不可靠),实则埋下隐蔽的竞态 bug,极难复现和调试。
常见误用场景与正确替代方案
有人试图用 struct 作锁来“节省内存”或“避免 new object”,这是典型误解。真正安全且轻量的做法只有一种:
private static readonly object _lock = new object(); // ✅ 推荐:静态、只读、专用// 错误示例(编译不过): // private readonly MyStruct _lockStruct = new MyStruct(); // lock(_lockStruct) { ... } // ❌ CS0185
// 危险示例(看似能跑,实则无效): // var s = new MyStruct(); // lock((object)s) { ... } // ❌ 每次 boxing 都是新对象,锁不住
如果需要保护某个 struct 字段(如 Point、DateTime),请把它封装进类中,再用私有 object 字段加锁:
- 不要锁
this、typeof(T)、字符串字面量(如"mylock"); - 不要锁 public 或可变对象(比如某个 List 实例,外部可能被替换);
- 若需高性能,考虑
Interlocked原子操作(适用于简单整数/引用赋值)或ConcurrentDictionary等无锁集合。
一句话收尾
struct 不是“不够格”,而是它天生不具备锁所需的对象身份一致性 —— 锁的本质是“同一个引用”,而 struct 的每次传递都在悄悄换人。别绕弯子,老老实实用 private static readonly object。










