c# - 如何在不使用 Lock 的情况下使操作组原子化
问题描述
我有一个state
变量,其感兴趣的字段是thread-safe
并一直fresh
使用一个ReaderWriterLockSlim
。我已经细化了对所有字段的访问,因为我在其他地方单独使用它们。
虽然对于字段的单独访问它工作正常,但我还需要进行一些原子操作。在这种情况下,我需要额外的操作lock
吗?
我有一个已经包含thread-safe
字段的状态变量:
internal class State {
private ReaderWriterLockSlim lck = new ReaderWriterLockSlim();
private bool cmd_PopUp;
private bool cmd_Shutdown;
private bool cmd_Delay;
public bool CMD_PopUp {
get {
try {
this.lck.EnterReadLock();
return this.cmd_PopUp;
} finally {
this.lck.ExitReadLock();
}
}
set {
try {
this.lck.EnterWriteLock();
this.cmd_PopUp = value;
} finally {
this.lck.ExitWriteLock();
}
}
}
//same goes for the other booleans
}
我已经有了这个线程安全的,并且我确保线程从内存中读取而不是从本地缓存中读取。但是我需要多个操作来完成原子操作。
原子操作
public async Task Run(State state)
{
while(true)
{
//do i need a lock here
if (state.CMD_Delay) {
state.CMD_Delay = false;
state.CMD_PopUp = false;
//end of potential lock ?
} else if (state.CMD_Shutdown) { //same here
state.CMD_PopUp = false;
state.CMD_Shutdown = false;
await SomeAction();
}
}
}
正如您在我的文章中看到的那样,我while
有一个if-else
需要原子操作组的地方。我应该使用额外的lock
还是有其他一些轻量级的解决方案?
解决方案
重用您现有的锁对我来说最有意义:
internal class State
{
...
public void SetDelayState()
{
try {
this.lck.EnterWriteLock();
this.cmd_Delay = false;
this.cmd_PopUp = false;
} finally {
this.lck.ExitWriteLock();
}
}
public void SetShutdownState()
{
try {
this.lck.EnterWriteLock();
this.cmd_PopUp = false;
this.cmd_Shutdown = false;
} finally {
this.lck.ExitWriteLock();
}
}
}
换句话说,将所有原子操作移动到您的State
类型的成员。
旁注:您几乎可以肯定不需要读/写锁。仅当满足以下所有条件时才应使用读取器/写入器锁:
- 一些代码路径是只读的,而另一些是读/写的。
- 读者远多于作家。
- 有大量连续读者。
如果其中任何一个不正确,那么lock
是更好的选择。
推荐阅读
- sql - 初级 Oracle SQL 错误消息 ORA-00900
- c++ - 常量表达式中引用类型的变量
- jquery - 如何在带有 vue 绑定的输入文本框中使用 JQuery inputmask?
- python - 试图将网页中的 JS 数据输出到 .html 输出文件中
- unix - 将行转置为列,在 shell 中保留一些行作为参考
- validation - 训练并没有提高模型在验证数据上的性能
- c++ - 无法从隐式继承的超类构造函数c ++创建子类
- sql-server - DatagridView 中的动态数据透视表
- c# - C# 日志和代码停止工作,如何解决?
- php - 将新主题和文件发布到 Brightsapce API 时出现错误 400