2016-12-27 1 views
4

나는 자바에서 source code of PriorityBlockingQueue을 읽고하고 궁금 해서요 :PriorityBlockingQueue에서 잠금/잠금 해제 추론은 무엇이 될 수 있습니까?

  1. 가 왜 tryGrow()() 방법, 바로 그 일이 비 제공하는 동안 획득 한 잠금을 해제 방법을하는 것입니다 차단 한 다음 대기열의 내용을 바꿀 준비가되면 다시 차단 하시겠습니까? 내 말은, 그것이 방금 가지고 있던 자물쇠를 지킬 수 있었음을 의미합니다 ...
  2. 어떻게 이런 식으로 작동합니까? 배열 복사본이 포함 된 대기열을 늘리는 동시에 동시 추가시 오작동을 일으키지 않습니다. 현재 추가가 대기열의 크기를 늘리면 추가 추가가 완전히 올 수 있습니까?

답변

3

메모리 할당이 상대적으로 느리고 배열이 잠금 해제되어있을 때 수행 할 수 있기 때문에.

잠금을 해제하면 다른 스레드가 (잠재적으로 큰) 새 배열을 할당하는 동안 계속 작동 할 수있게됩니다.

이 프로세스는 잠금없이 수행 할 수 있으므로 그렇게하는 것이 좋습니다. 당신은 최소한의 시간 동안 만 자물쇠를 개최해야합니다.

다른 스레드가 동시에이 작업을 수행하지 않도록 충분한 검사가 수행됩니다.

UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, 0, 1) 

은이 코드 섹션에 한 번에 하나의 스레드 만 허용합니다.

참고

lock.lock(); 
if (newArray != null && queue == array) { 

이 다시 잠금을 잡고 다음 교체하는 것입니다 배열이 시작시의 사본을 잡고 같은 하나라는 것을 확인합니다. 그 동안 대체 된 경우 다른 스레드가 배열을 확장했다는 가정하에 방금 생성 한 것을 버립니다.

여전히 동일하다면 이전 데이터를 새로운 더 큰 배열로 복사하고 다시 필드에 넣습니다.

Kamil 잘 설명합니다.

잠금 해제의 목적은 더 빠른 스레드가 대기열을 늘리므로 "더 나은 것"을 잠그는 동안 시간을 ​​낭비하지 않아도된다는 것입니다.

+1

제 의견으로는 코드를 읽은 후에 다른 스레드가 늘어나는 배열을 경주 할 수 있도록 추가하고 싶습니다. 그들은 기본적으로 다른 것을 할 수 없습니다. tryGrow에 가면 잠금을 해제 한 후에 요소를 넣으려고 시도하는 다른 요소가 tryGrow로만 이동할 수 있음을 확인할 수 있습니다. 잠금 해제의 목적은 더 빠른 스레드가 대기열을 늘릴 수 있도록하기위한 것이므로 "더 나은 대기열"을 잠그는 동안 시간을 ​​낭비하지 않아도됩니다. 나는 그것이 당신에게 의미가 있기를 바랍니다 :) –

+0

@ 카밀, 사실, 그것은 많은 의미가 있습니다. 그러나, 하나의 쓰레드가 풀어 져서 커지는 동안, 다음 하나는 커지려고 시도하고, 건너 뛰고 (초기 컨텍스트가 이미 커지기 때문에) 대기열을 바꾼다. – Belun

+1

알다시피, 그는하지 않는다. 덕분에 if (newArray! = null && queue == array), newArray는 null이됩니다. 다른 사람이 자랄 때까지 그는 자물쇠를 잠그고 자물쇠를 채우는 막 다른 길에있을 것입니다.그리고 나서 그들은 값을 넣을 것이고 배열을 성장시킨 스레드는 대기열을 교체하기 전에 잠금 장치 덕분에 먼저 나옵니다. 기본적으로 tryGrow에서 가장 빠르면 나머지는 기다려야합니다. –

관련 문제