Java 一个生产者一个状态对象有多个消费者
我有一位制片人:Java 一个生产者一个状态对象有多个消费者,java,java-8,locking,synchronized,producer-consumer,Java,Java 8,Locking,Synchronized,Producer Consumer,我有一位制片人: maintains ref StateRef to object StateObj implements method modify() method which modifies StateObj implements getRef() method which will be used by consumers 我有多个消费者,他们获取StateObj的ref并读取StateObj (生产者:修改stateObj,消费者读取(仅)stateObj) 所以,在典型的设计中,
maintains ref StateRef to object StateObj
implements method modify() method which modifies StateObj
implements getRef() method which will be used by consumers
我有多个消费者,他们获取StateObj的ref并读取StateObj
(生产者:修改stateObj,消费者读取(仅)stateObj)
所以,在典型的设计中,我需要由使用者读取锁,由生产者写入锁,这可能是高效的
但由于只有一个编写器,我将modify()方法编写为:
1. Ref refToCloneCopy = StateRef.clone()
2. update(refToCloneCopy)
3. StateRef = refToCloneCopy
优点:我不必对消费者强制执行读锁
我想确保在第三步未完成之前,“getRef()”将继续将ref返回到StateObj,在第三步之后,“getRef”将把ref返回到newState/ClonedObj
没有种族条件或一致性的要求,即,如果一半消费者收到oldState的ref,而另一半消费者收到newState的ref(clonedObj),则OK。但是getRef不应该返回一些奇怪的ref值,它应该返回oldState或newstate
我用Java8来做这个。。。有什么最好的方法可以有效地处理这一问题,而不会在消费者或生产者方面造成太多(或没有)锁定
更新:
即使我们决定在上面的第三步中使用锁,我想确保写入者/制作者的锁请求比消费者的锁请求具有更高的优先级,前提是您可以保证在创建新状态时返回旧状态,然后,您可以简单地将克隆和修改作为方法级变量,并将其分配给该方法末尾的stateRef字段。看来你在《修改》中提到的内容应该符合要求。不过,有一件事需要确定,那就是将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仅在modify方法的最后更改,并且只需将其设置为新的、已完全初始化的StateObj实例。请注意,volative关键字很重要,因为否则其他使用者线程可能会缓存stateRef的值,而看不到生产者线程的更改。它还可以防止编译器重新排序代码。但我是否需要在stateref=newobj的最后一个stmt处锁定,因为当stateref中的地址值改变时,这不是原子操作,或者Java原子中的是ref赋值?@sameer赋值应该可以。如果get和set需要是原子的,那么volatile是不够的。例如,如果您要执行类似于检查stateRef是否为null的操作,并仅在modify中设置它,那么您将需要synchronized或AtomicReference。但是在你陈述的用例中,volatile就足够了。