一个状态对象的一个生产者多个消费者
One Producer Multiple Consumers for one state Object
我有一位制作人:
maintains ref StateRef to object StateObj
implements method modify() method which modifies StateObj
implements getRef() method which will be used by consumers
我有多个消费者获取对 StateObj 的引用并读取 StateObj
(生产者:修改stateObj,消费者读取(仅)stateObj)
所以在典型的设计中,我需要消费者读锁和生产者写锁,这可能是低效的。
但是因为只有一个作者,我把modify()方法写成:
1. Ref refToCloneCopy = StateRef.clone()
2. update(refToCloneCopy)
3. StateRef = refToCloneCopy
优点:我不必对消费者强制执行读取锁定。
我想确保在第 3 步未完成之前 "getRef()" 将继续 return 引用 StateObj 并且在第 3 步 "getRef" 之后 return 引用newState/ClonedObj
没有竞争条件或一致性的要求,即如果一半消费者接收对 oldState 的 ref 而另一半消费者接收对 newState(clonedObj) 的 ref 就可以了。但是 getRef 不应该 return 一些奇怪的 ref 值,它应该 return oldState 或 new State。
我为此使用 Java8。 ...在消费者端或生产者端没有太多(或没有)锁定的情况下有效处理此问题的最佳方法是什么?
更新:
即使我们决定在上面的第 3 步中锁定,我也想确保 writer/producer 的锁定请求优先于消费者
的锁定请求
如果您保证在创建新状态时可以 return 旧状态,那么您可以简单地将克隆和修改作为方法级变量并将其分配给 stateRef该方法末尾的字段。看起来你提到的 modify 应该符合要求。不过,需要确定的一件事是将 stateRef 声明为 volatile。像这样:
class Producer {
private volatile StateObj stateRef;
StateObj getRef() {
return stateRef;
}
void modify() {
// Leave the instance field alone until modification is done
StateObj newObj = (StateObj) stateRef.clone();
// Do stuff to the new local variable reference. If any consumers
// call getRef while this is happening they get the stateRef value and
// not the newObj value.
// Once the newObj instance if fully initialized, set it as
// the stateRef instance.
stateRef = newObj;
}
}
您不会有任何生产者消费者与该值发生冲突,因为 stateRef 仅在修改方法的最后更改,并且它只是设置为新的、已经完全初始化的 StateObj 实例。请注意,volative 关键字很重要,否则其他消费者线程可能会缓存 stateRef 的值,而看不到来自生产者线程的更改。它还可以防止编译器重新排序代码。
我有一位制作人:
maintains ref StateRef to object StateObj
implements method modify() method which modifies StateObj
implements getRef() method which will be used by consumers
我有多个消费者获取对 StateObj 的引用并读取 StateObj
(生产者:修改stateObj,消费者读取(仅)stateObj)
所以在典型的设计中,我需要消费者读锁和生产者写锁,这可能是低效的。
但是因为只有一个作者,我把modify()方法写成:
1. Ref refToCloneCopy = StateRef.clone()
2. update(refToCloneCopy)
3. StateRef = refToCloneCopy
优点:我不必对消费者强制执行读取锁定。
我想确保在第 3 步未完成之前 "getRef()" 将继续 return 引用 StateObj 并且在第 3 步 "getRef" 之后 return 引用newState/ClonedObj
没有竞争条件或一致性的要求,即如果一半消费者接收对 oldState 的 ref 而另一半消费者接收对 newState(clonedObj) 的 ref 就可以了。但是 getRef 不应该 return 一些奇怪的 ref 值,它应该 return oldState 或 new State。
我为此使用 Java8。 ...在消费者端或生产者端没有太多(或没有)锁定的情况下有效处理此问题的最佳方法是什么?
更新: 即使我们决定在上面的第 3 步中锁定,我也想确保 writer/producer 的锁定请求优先于消费者
的锁定请求如果您保证在创建新状态时可以 return 旧状态,那么您可以简单地将克隆和修改作为方法级变量并将其分配给 stateRef该方法末尾的字段。看起来你提到的 modify 应该符合要求。不过,需要确定的一件事是将 stateRef 声明为 volatile。像这样:
class Producer {
private volatile StateObj stateRef;
StateObj getRef() {
return stateRef;
}
void modify() {
// Leave the instance field alone until modification is done
StateObj newObj = (StateObj) stateRef.clone();
// Do stuff to the new local variable reference. If any consumers
// call getRef while this is happening they get the stateRef value and
// not the newObj value.
// Once the newObj instance if fully initialized, set it as
// the stateRef instance.
stateRef = newObj;
}
}
您不会有任何生产者消费者与该值发生冲突,因为 stateRef 仅在修改方法的最后更改,并且它只是设置为新的、已经完全初始化的 StateObj 实例。请注意,volative 关键字很重要,否则其他消费者线程可能会缓存 stateRef 的值,而看不到来自生产者线程的更改。它还可以防止编译器重新排序代码。