2016-08-07 7 views
1

내가 가진 하나 개의 생산자가 :한 프로듀서 여러 소비자

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)

그래서 전형적인 디자인에서는 소비자가 읽기 잠금을하고 생산자가 쓰기 잠금을해야만 비효율적 일 수 있습니다.

1. Ref refToCloneCopy = StateRef.clone() 
2. update(refToCloneCopy) 
3. StateRef = refToCloneCopy 

장점 :

하지만, 내가 수정 쓴 하나의 작가() 등의 방법이 있기 때문에

나는 소비자 읽기 잠금을 적용 할 필요가 없습니다.

나는 3 단계가 완료되지 않을 때까지 "getRef는()"의 요구 사항이 없습니다

newState/ClonedObj에 심판을 반환 StateObj과 스텝 3 "getRef"다음에 심판을 반환하는 것입니다 수 있도록 할 경합 조건 또는 일관성 즉, 반쪽 소비자가 oldState 및 다른 반쪽 소비자에 대한 참조를 수신하면 OK를 newState (clonedObj)에 대한 참조를받습니다. 그러나 getRef는 이상한 ref 값을 돌려 보내서는 안되며 oldState 또는 new State를 반환해야합니다.

저는 이것을 위해 Java8을 사용하고 있습니다. ... 소비자 측면 또는 생산자 측면에서 너무 많이 (또는 아니오) 잠금없이 효율적으로 처리하는 가장 좋은 방법은 무엇입니까?

는 UPDATE : 당신이 그것을 보장하는 경우 우리는 위의 3 단계에서 잠금을하기로 결정하더라도, 나는 작가에 의해 잠금 요청/생산자가 소비자

답변

1

을하여 잠금 요청을 통해 높은 우선 순위를해야합니다 있는지 확인하려면 새로운 상태가 생성되는 동안 이전 상태를 반환하는 것이 좋습니다. 그러면 메서드 수준 변수로 복제 및 수정을 수행하고 해당 메서드의 끝에 stateRef 필드에 할당 할 수 있습니다. 당신이 수정안에 대해 언급 한 내용이 법안에 적합해야하는 것처럼 보입니다. 한 가지 확실한 것은 stateRef를 volatile로 선언하는 것입니다. 이런 식으로 뭔가 다음 stateRef에만 수정 방법의 맨 끝에 변경되고이 단순히 새로운, 이미 완전히 초기화 StateObj로 설정되어 있기 때문에

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; 
    } 
} 

당신은 가치있는 모든 생산자 소비자 충돌이되지 않습니다 예. volative 키워드는 다른 소비자 스레드가 stateRef의 값을 캐시 할 수 있고 제작자 스레드의 변경 사항을 볼 수 없기 때문에 중요합니다. 또한 컴파일러가 코드를 재정렬하는 것을 방지합니다.

+0

stateref = newobj의 마지막 상태에서 잠금을 취해야합니까? 상태 참조의 주소 값이 변경 될 때 원자 적 연산이 아니므로 –

+0

또는 Java 원자에서 참조를 할당합니까? –

+1

@ 님, 과제는 잘되어야합니다. get과 set이 원자적일 필요가 있으면 휘발성이 충분하지 않습니다. 예를 들어, stateRef가 null인지 확인하고, 수정시에만이를 설정하는 경우, synchronized 또는 AtomicReference가 필요합니다. 그러나 명시된 유스 케이스에서는 휘발성으로 충분할 것입니다. –