값을 다른 원자와 교환 할 수있는 참조 유형을 구현할 방법이 있습니까? 자바에서 원자 적으로 교환 할 수있는 AtomicReference를 생성 할 수 있습니까?
우리는하지만 다른
AtomicReference
와 지역 변수로 교환 할 수
AtomicReference
가 있습니다.
AtomicReference r1 = new AtomicReference("hello");
AtomicReference r2 = new AtomicReference("world");
을 두 작업의 조합을 교환 :
당신은 할 수
r1.set(r2.getAndSet(r1.get()));
을하지만이 모두가 "hello"
를 포함 할 경우, 사이에 일관성이없는 상태에서 그들을 떠난다. 또한 당신이 원자 적으로 그것들을 교환 할 수있다하더라도, 당신은 여전히 그것들을 원자 적으로 (쌍으로) 읽을 수 없습니다. 내가 할 수 있도록하고 싶습니다 무엇
입니다 : 다음
PairableAtomicReference r1 = new PairableAtomicReference("hello");
PairableAtomicReference r2 = new PairableAtomicReference("world");
AtomicRefPair rp = new AtomicRefPair(r1, r2);
Object[] oldVal, newVal;
do {
oldVal = rp.get();
newVal = new Object[] {oldVal[1], oldVal[0]};
} while (! rp.compareAndSet(oldVal, newVal));
값을 교환하고, 다른 스레드에서하기 :
AtomicRefPair otherRP = new AtomicRefPair(r1, r2);
System.out.println(Arrays.toString(otherRP.get()));
출력은 어느 것이 든 [hello, world]
또는 [world, hello]
.
주 : r1
다른 r3
말,
r1
및r2
이 작업을 위해 쌍으로하지만, 다른 스레드는 독립적으로 짝을 것입니다 가능성이- (불행하게도 그것이 내가 this solution을 사용할 수 없음을 의미합니다.) 수십만 개의 이러한 참조가 될 것이므로 세계
ReentrantLock
은 큰 병목이 될 것입니다. rp
및otherRP
은 반드시 스레드간에 공유되지 않으므로 단순히 잠그면 작동하지 않습니다. 그들은 interned 일 수 있지만 인턴 풀은 다른 병목 현상이 될 자체 동기화가 필요합니다.- 여기에 2 개의 참조 그룹 만 만들었지 만 3 개 이상 그룹으로 묶을 수있는 능력은 보너스가 될 것입니다.
AtomicRefPair
의 잠금 해제 버전을 구현할 수 있습니까? 나는 그렇지 않다는 직감을 가지고있다. 그러나 그렇지 않다면 어쩌면 어딘가에 이유를 설명하는 기사가있을 것이다.관련
: How do I atomically swap 2 ints in C#?
Guava에는 ConcurrentHashMap을 사용하는 Interner가 있으므로, 평균적으로 경쟁이 임의적으로 작을 수 있습니다. – maaartinus