java.util.concurrent
API는로 불리는 클래스를 제공합니다.이 클래스 Lock
는 기본적으로 중요한 리소스에 액세스하기 위해 컨트롤을 직렬화합니다. 이 같은 방법을 제공 park()
하고 unpark()
.
synchronized
키워드와 사용 wait()
및 notify() notifyAll()
메소드를 사용할 수 있다면 비슷한 일을 할 수 있습니다 .
나는 이것들 중 어느 것이 실제로 더 낫고 왜 그런지 궁금합니다.
답변
단순히 객체를 잠그는 경우 사용하고 싶습니다. synchronized
예:
Lock.acquire();
doSomethingNifty(); // Throws a NPE!
Lock.release(); // Oh noes, we never release the lock!
try{} finally{}
어디서나 명시 적으로해야 합니다.
동기화 된 반면에 잘못하는 것은 매우 명확하고 불가능합니다.
synchronized(myObject) {
doSomethingNifty();
}
즉, Lock
s는 그러한 깨끗한 방식으로 획득하고 풀 수없는 더 복잡한 것들에 더 유용 할 수 있습니다. 솔직히 맨손으로 사용하는 것을 피하고 Lock
a CyclicBarrier
또는 a 와 같은보다 정교한 동시성 제어를 사용하는 것이 LinkedBlockingQueue
좋습니다.
내가 사용하는 이유가 없었습니다 wait()
또는 notify()
하지만 좋은 것들이있을 수 있습니다.
답변
나는 이것들 중 어느 것이 실제로 더 낫고 왜 그런지 궁금합니다.
Lock
그리고 Condition
(및 다른 새 concurrent
클래스)는 도구 상자를위한 더 많은 도구 라는 것을 알았습니다 . 나는 오래된 도리 ( synchronized
키워드)로 필요한 모든 것을 할 수 있었지만 어떤 상황에서는 사용하기가 어색했습니다. 도구 상자에 고무 망치, 볼펜 해머, 프라이 바 및 네일 펀치와 같은 도구를 더 추가하면 이러한 어색한 상황이 훨씬 간단 해졌습니다. 그러나 오래된 클로 해머는 여전히 그 사용 점유율을 봅니다.
나는 하나가 다른 것보다 실제로 “더 낫다”고 생각하지는 않지만, 각각은 다른 문제에 더 잘 맞습니다. 간단히 말해서, 간단한 모델과 범위 지향적 특성은 synchronized
코드의 버그로부터 나를 보호 하는 데 도움이되지만 더 복잡한 시나리오에서는 동일한 이점이 방해가되는 경우가 있습니다. 해결을 돕기 위해 동시 패키지가 생성 된보다 복잡한 시나리오입니다. 그러나이 상위 구조를 사용하려면 코드에서보다 명확하고 신중한 관리가 필요합니다.
===
나는 생각 의 JavaDoc가 사이의 차이를 잘 설명하지 Lock
하고 synchronized
(강조는 내입니다) :
잠금 구현은 동기화 된 메소드 및 명령문을 사용하여 얻을 수있는 것보다 더 광범위한 잠금 조작을 제공 합니다. 그것들은 보다 유연한 구조화를 허용 하고 , 상당히 다른 속성을 가질 수 있으며, 연관된 여러 개의 Condition 객체를 지원할 수 있습니다 .
…
의 사용 동기화 방법 이나 문은 모든 객체와 관련된 암묵의 감시 락에의 액세스를 제공하지만, 힘 모든 잠금 획득 및 해제는 블록 구조 방식으로 발생하는 다음과 같은 경우 여러 잠금이 되어 인수 가 반대 순서로 발표해야 하고, 모든 잠금은 잠금을 획득 한 것과 동일한 어휘 범위에서 해제해야합니다 .
동기화 된 메소드 및 명령문 의 범위 지정 메커니즘을 사용하면 모니터 잠금을 사용하여 프로그래밍하는 것이 훨씬 쉬워지고 잠금 과 관련된 많은 일반적인 프로그래밍 오류를 피할 수 있지만보다 유연한 방식으로 잠금으로 작업해야하는 경우가 있습니다. 예를 들어, * 동시에 액세스되는 데이터 구조를 순회하기위한 * 일부 알고리즘 * 은 “Hand-over-hand”또는 “chain locking”을 사용해야합니다. 노드 A, 노드 B의 잠금을 획득 한 다음 A를 해제하고 C를 획득합니다. 그런 다음 B를 놓고 D 등을 얻습니다. 의 구현 잠금 인터페이스는 이런 종류의 테크닉을 이용할 수있게 다른 스코프 내에서 락을 취득 및 해제 할 수 있도록 하고,여러 개의 잠금 장치를 임의의 순서로 획득 및 해제 할 수 있습니다 .
이러한 유연성 증가로 인해 추가 책임이 따릅니다 . 블록 구조 잠금 이 없으면 동기화 된 메소드 및 명령문에서 발생 하는 자동 잠금 해제가 제거됩니다 . 대부분의 경우 다음 관용구를 사용해야합니다.
…
때 잠금 및 잠금 해제가 다른 범위에서 발생 ,주의가주의해야 보장 이 유지되는 잠금이 동시에 실행되는 모든 코드 마지막으로-시도에 의해 보호 또는 시도 – 캐치되어 하는 잠금이 해제되어 있는지 확인합니다 필요한 경우.
잠금 구현은 제공하는 추가 기능 제공하여 동기화 방법 및 문장의 사용에를 취득하는 비 차단 시도 잠금을 (설정된 tryLock ()), 시도 중단 될 수있는 잠금 획득 lockInterruptibly을 (() 및 시도 획득 제한 시간을 초과 할 수있는 잠금 (tryLock (long, TimeUnit))
…
답변
당신의 유틸리티 모든 것을 달성 할 수있는 java.util.concurrent의이 같은 낮은 수준의 프리미티브와 함께 할을 synchronized
, volatile
또는 대기 / 통지
그러나 동시성은 까다 롭고 대부분의 사람들은 적어도 일부가 잘못되어 코드가 잘못되었거나 비효율적입니다 (또는 둘 다).
동시 API는 고급 접근 방식을 제공하므로 사용하기가 더 쉽고 안전합니다. 간단히 말해 synchronized, volatile, wait, notify
더 이상 직접 사용할 필요가 없습니다.
잠금 자체가이 도구 상자의 낮은 수준의 측면에 클래스, 당신도 (당신이 사용할 수있는 바로 그 중 하나를 사용하지 않아도 Queues
과 세마포 등 물건, 대부분의 시간을).
답변
사용하려는 이유에 4 개 가지 주요 요소가있다 synchronized
거나 java.util.concurrent.Lock
.
참고 : 동기화 잠금은 본질적 잠금을 말할 때 의미합니다.
-
Java 5가 ReentrantLocks와 함께 나왔을 때, 고유 잠금과는 상당히 다른 처리량 차이가 있음이 증명되었습니다. 더 빠른 잠금 메커니즘을 찾고 1.5를 실행중인 경우 jucReentrantLock을 고려하십시오. Java 6의 고유 잠금 기능은 이제 비슷합니다.
-
jucLock에는 잠금 메커니즘이 다릅니다. 잠금 인터럽트 가능-잠금 스레드가 중단 될 때까지 잠금을 시도하십시오. 시간 제한 잠금-일정 시간 동안 잠금을 시도하고 성공하지 못하면 포기합니다. tryLock-다른 스레드가 잠금을 잡고 있으면 잠금을 시도합니다. 이 모든 것은 간단한 자물쇠와 함께 포함되어 있습니다. 본질 잠금은 단순한 잠금 만 제공합니다
- 스타일. 1과 2가 모두 나 자신을 포함하여 대부분의 사람들과 관련이있는 범주에 속하지 않으면 본질적 잠금 의미 체계가 읽기 쉽고 덜 간결한 jucLock 잠금을 찾을 수 있습니다.
- 여러 조건. 잠근 개체는 알림을 받고 단일 사례 만 기다릴 수 있습니다. Lock의 newCondition 메서드를 사용하면 단일 Lock이 여러 가지 이유로 대기하거나 신호를 보낼 수 있습니다. 실제로 실제로는이 기능이 실제로 필요하지는 않지만 필요한 사람들에게는 유용한 기능입니다.
답변
Bert F 답변 위에 더 많은 것을 추가하고 싶습니다 .
Locks
암시 적 모니터 ( synchronized
자물쇠) 보다 더 세밀한 세밀한 잠금 제어를위한 다양한 방법 지원
잠금은 공유 자원에 대한 독점 액세스를 제공합니다. 한 번에 하나의 스레드 만 잠금을 획득 할 수 있으며 공유 자원에 대한 모든 액세스는 먼저 잠금을 획득해야합니다. 그러나 일부 잠금은 ReadWriteLock의 읽기 잠금과 같은 공유 리소스에 대한 동시 액세스를 허용 할 수 있습니다.
설명서 페이지 에서 동기화 잠금의 장점
-
동기화 된 메소드 또는 명령문을 사용하면 모든 오브젝트와 연관된 내재 된 모니터 잠금에 액세스 할 수 있지만 모든 잠금 획득 및 해제는 블록 구조 방식으로 발생합니다.
-
잠금 구현은 잠금을 획득하려는 비 차단 시도
lock (tryLock())
, 중단 될lockInterruptibly()
수있는 잠금을 획득하려는 시도 및 잠금을 획득하려는 시도를 제공함으로써 동기화 된 메소드 및 명령문의 사용에 대한 추가 기능을 제공합니다timeout (tryLock(long, TimeUnit))
. -
Lock 클래스는 또한 보장 된 순서, 재진입되지 않은 사용 또는 교착 상태 감지 와 같이 암시 적 모니터 잠금과는 상당히 다른 동작 및 의미를 제공 할 수 있습니다.
ReentrantLock : 내 이해에 따라 간단한 용어로, ReentrantLock
하나의 중요한 섹션에서 다른 중요한 섹션으로 객체를 다시 입력 할 수 있습니다. 하나의 중요한 섹션을 입력 할 수있는 잠금이 이미 있으므로 현재 잠금을 사용하여 동일한 객체에 다른 중요한 섹션을 추가 할 수 있습니다.
ReentrantLock
이 기사에 따른 주요 기능
- 방해 할 수있는 능력.
- 잠금을 기다리는 동안 시간 종료 기능.
- 공정한 자물쇠를 만드는 힘.
- 잠금 대기중인 스레드 목록을 가져 오는 API
- 차단하지 않고 잠금을 시도 할 수있는 유연성.
ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
읽기 및 쓰기 작업에서 세분화 된 잠금에 대한 제어를 추가로 획득 하는 데 사용할 수 있습니다 .
이 세 가지 ReentrantLock 외에도 Java 8은 하나 이상의 잠금을 제공합니다.
StampedLock :
Java 8에는 위의 예와 같이 읽기 및 쓰기 잠금도 지원하는 StampedLock이라는 새로운 종류의 잠금이 제공됩니다. ReadWriteLock과 달리 StampedLock의 잠금 방법은 long 값으로 표시된 스탬프를 반환합니다.
이 스탬프를 사용하여 잠금을 해제하거나 잠금이 여전히 유효한지 확인할 수 있습니다. 또한 스탬프 잠금은 낙관적 잠금이라는 다른 잠금 모드를 지원합니다.
다른 유형 및 잠금 사용법에 대한 이 기사 를 살펴보십시오 .ReentrantLock
StampedLock
답변
가장 큰 차이점은 공정성입니다. 즉, 요청이 FIFO를 처리합니까, 아니면 참여할 수 있습니까? 메소드 레벨 동기화는 잠금의 페어 또는 FIFO 할당을 보장합니다. 사용
synchronized(foo) {
}
또는
lock.acquire(); .....lock.release();
공정성을 보장하지 않습니다.
잠금에 대해 많은 경합이있는 경우 새로운 요청이 잠금을 받고 이전 요청이 중단되는 위치에서 쉽게 참여할 수 있습니다. 잠금을 위해 200 개의 스레드가 짧은 순서로 도착하고 두 번째 스레드가 마지막으로 처리되는 경우를 보았습니다. 일부 응용 프로그램에는 문제가 없지만 다른 응용 프로그램에는 치명적입니다.
이 주제에 대한 자세한 내용은 Brian Goetz의 “실제 Java 동시성”책, 13.3 절을 참조하십시오.
답변
Brian Goetz의 “Java Concurrency In Practice”책, 섹션 13.3 : “… 기본 ReentrantLock과 마찬가지로 내장 잠금은 결정 론적 공정성을 보장하지 않지만 대부분의 잠금 구현에 대한 통계적 공정성 보장은 거의 모든 상황에 충분합니다 …”
