source

동기화 vs 잠금

lovecheck 2022. 10. 30. 17:57
반응형

동기화 vs 잠금

java.util.concurrentAPI는 다음과 같은 클래스를 제공합니다.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는, 그러한 방법으로 입수해 릴리스 할 수 없는 보다 복잡한 경우에 도움이 되는 경우가 있습니다.저는 솔직히 베어 사용을 피하고 싶습니다.Lock우선은, 보다 고도의 동시성 제어(예:CyclicBarrier또는LinkedBlockingQueue고객님의 요구에 부응하는 경우.

난 한번도 이걸 써본 적이 없어wait()또는notify()좋은 게 있을지도 몰라요.

이 중 어떤 것이 실제로 더 나은지 궁금하고 그 이유는 무엇입니까?

나는 그것을 발견했다.Lock그리고.Condition(기타 신규)concurrentclasses)는 툴박스를 위한 도구일 뿐입니다.나는 내 오래된 발톱 망치로 내가 필요한 모든 것을 할 수 있었다.synchronized키워드)를 사용하고 있습니다만, 상황에 따라서는 사용하기 불편할 수 있습니다.도구 상자에 도구를 더 추가하자 이러한 어색한 상황들 중 몇 가지가 훨씬 더 간단해졌다: 고무 망치, 볼펜 망치, 프라이바, 그리고 손톱 펀치.하지만, 내 오래된 발톱 망치는 여전히 쓰임새가 있다.

저는 둘 중 하나가 다른 것보다 더 낫다고 생각하지 않고, 오히려 각각이 다른 문제에 더 적합하다고 생각합니다.간단히 말하면, 심플한 모델과 스코프 지향의 성질입니다.synchronized코드 내의 버그로부터 보호하는데 도움이 되지만, 같은 장점이 더 복잡한 시나리오에서는 장애가 될 수 있습니다.이러한 보다 복잡한 시나리오에서 동시 패키지는 문제를 해결하기 위해 작성되었습니다.그러나 이 상위 수준의 구성을 사용하려면 코드 내에서 보다 명확하고 세심한 관리가 필요합니다.

===

JavaDoc이 잘 설명한다고 생각합니다.Lock그리고.synchronized(중요한 것은 내 것이다)

잠금 구현은 동기화된 메서드 및 문을 사용하여 얻을 수 있는 것보다 더 광범위한 잠금 작업제공합니다.이러한 기능을 통해 보다 유연한 구조가 가능하며, 특성이 상당히 다를 수 있으며, 여러 개의 연관된 조건 개체를 지원할 수 있습니다.

...

동기화된 메서드 또는 스테이트먼트를 사용하면 모든 오브젝트와 관련된 암묵적인 모니터잠금 접근은 가능하지만 모든 잠금 획득해제는 블록 구조이루어집니다.복수의 잠금을 취득경우에는 반대 순서해제해야 하며 모든 잠금은 동일한 사전 범위에서 해제되어야 합니다.취득되었습니다.

동기화된 메서드 및 문의 범위 지정 메커니즘을 사용하면 모니터 잠금사용하여 프로그래밍이 훨씬 쉬워지고 잠금과 관련된 많은 일반적인 프로그래밍 오류를 방지할 수 있지만 잠금을 보다 유연하게 사용해야 할 경우가 있습니다.를 들어 **동시에 액세스한 데이터 구조를 통과하기 위한 일부 알고리즘*에서는 "핸드오버 핸드" 또는 "체인 잠금"을 사용해야 합니다. 노드 A의 잠금을 취득한 후 노드 B를 취득하고 다음으로 노드 B를 취득한 후 C를 취득한 후 B를 해방하고 D를 취득하는 등의 방법이 있습니다.잠금 인터페이스를 구현하면 잠금을 다른 범위에서 획득해제할 수 있고 여러 잠금을 임의의 순서획득해제할 수 있으므로 이러한 기술을 사용할 수 있습니다.

유연성이 향상됨에 따라 책임도 증가합니다.블록 구조 잠금이 없으면 동기화된 메서드 및 문장에서 발생하는 잠금이 자동으로 해제되지 않습니다.대부분의 경우 다음 관용구를 사용해야 합니다.

...

잠금잠금 해제가 서로 다른 범위에서 발생할 경우 잠금이 유지되는 동안 실행되는 모든 코드가 Try-Finally 또는 Try-Catch의해 보호되어 필요할 때 잠금이 해제되도록 주의해야 합니다.

잠금 실장은 잠금 취득을 위한 비블로킹 시도(tryLock()), 중단될 수 있는 잠금 취득 시도(lockInterruptible() 및 타임아웃할 있는 잠금 취득 시도(tryLock(long, TimeUnit))를 제공함으로써 동기화된 메서드 및 스테이트먼트의 사용에 대한 추가 기능제공합니다.

...

java.util.concurrent의 유틸리티가 수행하는 모든 작업을 다음과 같은 낮은 수준의 프리미티브로 수행할 수 있습니다.synchronized,volatile또는 대기/알림

그러나 동시성은 까다롭고, 대부분의 사람들은 최소한 일부만 잘못 알고 있기 때문에 코드가 부정확하거나 비효율적입니다(또는 둘 다입니다.

동시 API는 보다 사용하기 쉽고 안전한 높은 수준의 접근 방식을 제공합니다.간단히 말하면, 이 기능을 사용할 필요가 없습니다.synchronized, volatile, wait, notify더 이상 직접적으로.

Lock 클래스 자체는 이 툴박스의 하위 레벨에 있으며 직접 사용할 필요도 없습니다(사용할 수도 있습니다).Queues대부분의 경우 세마포어 등).

4가지 에서 왜 4가지 를 사용하고 알 수 .synchronized ★★★★★★★★★★★★★★★★★」java.util.concurrent.Lock.

주의: 동기 잠금이란 고유 잠금이라는 뜻입니다.

  1. Java 5가 ReentrantLocks와 함께 출시되었을 때, 이들은 본질적인 잠금과 비교하여 상당히 현저한 스루풋 차이를 보였습니다.보다 빠른 잠금 메커니즘을 찾고 있으며 1.5를 실행하고 있다면 j.u.c.를 고려해 주십시오.재입력 잠금Java 6의 고유한 잠금 기능은 이제 유사합니다.

  2. J.U.C.Lock에는 잠금 메커니즘이 다릅니다.잠금 인터럽트 가능 - 잠금 스레드가 중단될 때까지 잠금 시도, 일정 시간 동안 잠금 시도했다가 실패하면 포기, tryLock - 다른 스레드가 잠금 포기를 유지하는 경우 잠금을 시도합니다.이 모든 것은 간단한 잠금 장치 이외에 포함되어 있습니다.내장 잠금 기능은 단순한 잠금 기능만 제공합니다.

  3. 스타일. 1과 2가 나를 포함한 대부분의 사람들과 관련된 범주에 속하지 않는다면, 내재된 잠금 세미노틱스는 읽기 쉽고 장황하지 않을 것입니다.잠금 장치
  4. 여러 조건잠근 개체는 단일 케이스에 대해서만 알림을 받고 대기할 수 있습니다.Lock의 newCondition 메서드는 단일 Lock이 대기 또는 시그널링을 해야 하는 여러 가지 이유를 가질 수 있도록 합니다.아직 실제로 이 기능은 필요하지 않지만, 필요한 사람에게는 좋은 기능입니다.

Bert F 답변 에 몇 가지 사항을 추가하고 싶습니다.

Locks 제어를 위한 synchronized 삭제)

잠금을 사용하면 공유 리소스에 대한 배타적 액세스가 제공됩니다. 한 번에 하나의 스레드만 잠금을 취득할 수 있으며 공유 리소스에 대한 모든 액세스에는 먼저 잠금을 취득해야 합니다.그러나 일부 잠금으로 인해 ReadWriteLock의 읽기 잠금과 같은 공유 리소스에 대한 동시 액세스가 허용될 수 있습니다.

문서 페이지에서 동기화에 대한 잠금의 이점

  1. 동기화된 메서드 또는 스테이트먼트를 사용하면 모든 객체와 관련된 암묵적인 모니터 잠금에 액세스할 수 있지만 모든 잠금 획득 및 해제는 블록 구조로 이루어집니다.

  2. 잠금 된 메서드 및을 제공합니다. ""를 할 수 있도록 합니다.이것에 의해, 다음의 정보를 취득하기 위한 비블로킹 시도를 실시할 수 있습니다.lock (tryLock())수 잠금」).lockInterruptibly() 시도입니다.timeout (tryLock(long, TimeUnit)).

  3. Lock 클래스는 암묵적인 모니터 잠금과는 상당히 다른 동작과 의미(예: 순서 보장, 비반복 사용 또는 교착 상태 검출)를 제공할 수도 있습니다.

재입력 잠금:간단히 말해서, 제가 아는 바로는,ReentrantLock는 오브젝트가 하나의 크리티컬섹션에서 다른 크리티컬섹션으로 재진입할 수 있도록 합니다.이미 하나의 크리티컬섹션으로 들어가기 위한 잠금이 설정되어 있기 때문에 현재 잠금을 사용하여 동일한 오브젝트의 다른 크리티컬섹션을 입력할 수 있습니다.

ReentrantLock 기사의 주요 특징

  1. 중단 없이 잠글 수 있습니다.
  2. 잠금을 기다리는 동안 시간 초과가 가능합니다.
  3. 공정한 잠금을 만들 수 있는 힘.
  4. 잠금 대기 스레드 목록을 가져오는 API입니다.
  5. 차단하지 않고 잠금을 시도할 수 있는 유연성.

하시면 됩니다.ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock읽기 및 쓰기 작업에 대한 세부적인 잠금 제어를 더욱 강화할 수 있습니다.

이들 3개의 ReentrantLocks 외에 Java 8은 1개의 Lock을 더 제공합니다.

스탬프 잠금:

Java 8에는 위의 예시와 같이 읽기 및 쓰기 잠금도 지원하는 StampedLock이라는 새로운 종류의 잠금이 포함되어 있습니다.ReadWriteLock과 달리 StampedLock의 잠금 방법은 긴 값으로 표시된 스탬프를 반환합니다.

이러한 스탬프를 사용하여 잠금을 해제하거나 잠금이 여전히 유효한지 확인할 수 있습니다.추가로 스탬프가 찍힌 잠금 장치는 옵티멀 잠금이라는 또 다른 잠금 모드를 지원합니다.

다양한 타입의 사용법에 관한 이 기사를 봐 주세요.ReentrantLock ★★★★★★★★★★★★★★★★★」StampedLockcontracts.contracts locks locks locks locks locks locks

주요 차이점은 공정성입니다. 즉, 요청이 처리되는 FIFO이거나 간섭이 발생할 수 있습니다.메서드 레벨 동기화에 의해 잠금이 균등하게 또는 FIFO로 할당됩니다.사용.

synchronized(foo) {
}

또는

lock.acquire(); .....lock.release();

공정성을 보장하지 않습니다.

잠금 경합이 심한 경우 새 요청이 잠금을 받고 이전 요청이 고착되는 간섭이 쉽게 발생할 수 있습니다.200개의 스레드가 짧은 순서로 도착하고 두 번째 스레드는 마지막에 도착하는 경우를 본 적이 있습니다.이것은 일부 어플리케이션에서는 괜찮지만 다른 어플리케이션에서는 치명적입니다.

이 주제에 대한 자세한 내용은 Brian Goetz의 "Java Concurrency In Practice" 책 섹션 13.3을 참조하십시오.

잠금과 동기화 간의 주요 차이점:

  • 잠금을 사용하면 임의의 순서로 잠금을 해제하고 취득할 수 있습니다.
  • 동기화된 경우 획득한 순서대로만 잠금을 해제할 수 있습니다.

Brian Goetz의 "Java Concurrency In Practice" 책, 섹션 13.3: "...디폴트 ReentrantLock과 마찬가지로 본질적인 잠금은 결정론적 공정성 보장을 제공하지 않지만 대부분의 잠금 구현의 통계적 공정성 보장은 거의 모든 상황에서 충분합니다.."

잠금은 프로그래머의 삶을 더 편하게 해준다.다음은 잠금으로 쉽게 달성할 수 있는 몇 가지 상황입니다.

  1. 한 가지 방법으로 잠그고 다른 방법으로 잠금을 해제합니다.
  2. 다만, 2개의 다른 코드로 동작하는 2개의 스레드가 있는 경우는, 1개의 스레드에 2개의 스레드의 특정 코드로 동작하는 전제 조건이 있습니다(다른 일부 스레드도 2개의 스레드에서 동시에 동작합니다).공유 잠금을 사용하면 이 문제를 쉽게 해결할 수 있습니다.
  3. 모니터의 실장.예를 들어, 다른 많은 스레드에서 put and get 메서드가 실행되는 단순 대기열입니다.단, 여러 put(또는 get) 메서드를 동시에 실행하거나 put 메서드와 get 메서드를 동시에 실행하지 않도록 합니다.개인 자물쇠가 있으면 생활이 훨씬 쉬워집니다.

한편, 잠금 및 조건은 동기화된 메커니즘에 기초하고 있습니다.따라서 잠금을 사용하여 얻을 수 있는 것과 동일한 기능을 확실하게 실현할 수 있습니다.그러나 복잡한 시나리오를 동기화하여 해결하면 생활이 어려워지고 실제 문제 해결에서 벗어날 수 있습니다.

잠금 및 동기화 블록은 둘 다 동일한 용도로 사용되지만 용도에 따라 다릅니다.아래 부분을 고려하십시오.

void randomFunction(){
.
.
.
synchronize(this){
//do some functionality
}

.
.
.
synchronize(this)
{
// do some functionality
}


} // end of randomFunction

위의 경우 스레드가 동기화 블록에 들어가면 다른 블록도 잠깁니다.동일한 개체에 여러 개의 동기화 블록이 있는 경우 모든 블록이 잠깁니다.이러한 상황에서는 java.util.concurrent 입니다.블록의 원치 않는 잠금을 방지하기 위해 잠금을 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/4201713/synchronization-vs-lock

반응형