锁定与 Interlocked.Exchange
lock vs Interlocked.Exchange
我有一个应用程序不断(+-100 毫秒)从 PLC 读取命令,然后将它们放入一个模型中,然后由多个客户端读取。
为此,我使用了 lock 语句。
订单阅读线程:
lock (model) {
//update object
}
阅读的客户:
lock (model) {
//serialize object to json string
}
send over tcp stream to client.
但我也可以用于更新:
Interlocked.ExChange(oldObj, newObj)
我不希望我的客户必须等待订单读取线程中发生的锁定。
而且我绝对不希望客户阻止我的订单阅读线程。
我最好使用联锁吗?
谢谢指教!
是的,您最好使用 Interlocked
,因为它的效率更高,因为它主要转换为单个原子操作。
但是,如果您不介意客户端仍然稍微读取旧对象,您甚至可以不使用 Interlocked 并设置一个新实例。
碰巧获得新实例的客户端将获得更新的数据,而那些没有获得新实例的客户端将在下一次检查中获得它。
如果您的单一制作人正在创建一个全新的模型,并将其分配给共享字段,那么是的,Interlocked.Exchange
是正确的选择。
如果您的制作人不需要知道旧模型是什么,那么您可以使用Volatile.Write(ref _sharedObj, newObj)
来简化它。
只要注意三件事:
- 使用
Volatile.Read
读取您的共享对象。
消费者应该每个工作单元读取一次共享状态
//incorrect - _sharedObj is not guaranteed to be the same in both reads
var x = CalculateX(_sharedObj);
var y = CalculateY(_sharedObj);
//correct
var obj = Volatile.Read(ref _sharedObj);
var x = CalculateX(obj);
var y = CalculateY(obj);
消费者有时会使用稍微过时的模型。所以请确保使用稍微过时的对象不会给您带来任何麻烦
var obj = _sharedObj;
// If _sharedObj is exchanged here, then `obj` will be outdated
var x = CalculateX(obj);
var y = CalculateY(obj);
我有一个应用程序不断(+-100 毫秒)从 PLC 读取命令,然后将它们放入一个模型中,然后由多个客户端读取。 为此,我使用了 lock 语句。
订单阅读线程:
lock (model) {
//update object
}
阅读的客户:
lock (model) {
//serialize object to json string
}
send over tcp stream to client.
但我也可以用于更新:
Interlocked.ExChange(oldObj, newObj)
我不希望我的客户必须等待订单读取线程中发生的锁定。 而且我绝对不希望客户阻止我的订单阅读线程。
我最好使用联锁吗?
谢谢指教!
是的,您最好使用 Interlocked
,因为它的效率更高,因为它主要转换为单个原子操作。
但是,如果您不介意客户端仍然稍微读取旧对象,您甚至可以不使用 Interlocked 并设置一个新实例。
碰巧获得新实例的客户端将获得更新的数据,而那些没有获得新实例的客户端将在下一次检查中获得它。
如果您的单一制作人正在创建一个全新的模型,并将其分配给共享字段,那么是的,Interlocked.Exchange
是正确的选择。
如果您的制作人不需要知道旧模型是什么,那么您可以使用Volatile.Write(ref _sharedObj, newObj)
来简化它。
只要注意三件事:
- 使用
Volatile.Read
读取您的共享对象。 消费者应该每个工作单元读取一次共享状态
//incorrect - _sharedObj is not guaranteed to be the same in both reads var x = CalculateX(_sharedObj); var y = CalculateY(_sharedObj); //correct var obj = Volatile.Read(ref _sharedObj); var x = CalculateX(obj); var y = CalculateY(obj);
消费者有时会使用稍微过时的模型。所以请确保使用稍微过时的对象不会给您带来任何麻烦
var obj = _sharedObj; // If _sharedObj is exchanged here, then `obj` will be outdated var x = CalculateX(obj); var y = CalculateY(obj);