线程安全枚举结合switch case使用:能否直接调用属性?
回答:完全可以直接在switch中调用该属性!
放心用!你完全可以像示例里那样,在switch语句中直接调用MyEnumVal属性,这在线程安全和逻辑正确性上都没毛病。
为啥这么说?
咱们拆解下你的代码逻辑就懂了:
你的
MyEnumVal属性的get方法加了lock,这就保证了:- 每次读取都会拿到最新的、完整的枚举值(也就是内存可见性),不会因为多线程的缓存机制读到旧值;
- 虽说枚举作为值类型,它的读取操作本身在.NET里是原子性的,但这里的
lock主要是和setter的逻辑同步,确保读写操作的有序性,彻底杜绝任何潜在的线程问题。
当你在
switch里写this.MyEnumVal时,本质是先执行get方法拿到当前的枚举值(这一步已经通过lock保证了线程安全的快照),然后用这个值去走switch的分支判断。而且因为枚举是值类型,你拿到的是个副本——哪怕在switch执行的过程中,有其他线程修改了MyEnumVal,也不会影响当前switch的分支逻辑,因为你判断用的是当时拿到的那个固定值。
对应代码参考
你的线程安全属性实现:
private object myEnumValLock = new object(); private MyEnum _myEnumVal; public MyEnum MyEnumVal { get { lock(this.myEnumValLock) { return this._myEnumVal; } } set { lock(this.myEnumValLock) { if (value != this._myEnumVal) { this.HandleNewMyEnumVal(this._myEnumVal, value); this._myEnumVal = value; } } } }
你写的switch调用方式:
private void MyFunc() { switch (this.MyEnumVal) { case MyEnum.First: // Do Something break; // 其他分支... } }
这种用法完全没问题,而且不会引入任何线程安全隐患——毕竟get方法的lock已经帮你把读取的安全性处理好了。
额外小提醒
如果你的MyEnum是个简单枚举(没有复杂的底层结构),理论上也可以考虑用volatile关键字优化(不过volatile不直接支持枚举,得转成对应的基础类型比如int),但你当前的实现已经足够安全还容易看懂,没必要特意改。
内容的提问来源于stack exchange,提问作者Xpleria
相关产品推荐
相关产品推荐

