java 병발(21) 분석 동기화기
8102 단어 java 병발
대부분의 동기화기는 특정한 구역 (임계 구역) 을 보호하는 데 사용되는 코드로, 이 코드들은 여러 라인에 동시에 접근할 수 있다.이 목표를 달성하려면 동기화기는 일반적으로 다음과 같은 기능을 지원해야 한다.
컨디션
동기화기의 상태는 어떤 라인에 접근 권한이 있는지 확인하는 데 사용됩니다.Lock에서 상태는 boolean 유형이며 현재 Lock 객체가 잠겨 있는지 여부를 나타냅니다.BoundedSemaphore에서 내부 상태는 카운터 (int 형식) 와 상한 (int 형식) 을 포함하며, 각각 현재 얻은 허가수와 최대 얻은 허가수를 표시합니다.BlockingQueue의 상태는 대기열의 요소 목록과 대기열의 최대 용량입니다.
다음은 Lock과 BoundedSemaphore의 두 코드 세그먼트입니다.
public class Lock{
//state is kept here
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
...
}
public class BoundedSemaphore {
//state is kept here
private int signals = 0;
private int bound = 0;
public BoundedSemaphore(int upperBound){
this.bound = upperBound;
}
public synchronized void take() throws InterruptedException{
while(this.signals == bound) wait();
this.signal++;
this.notify();
}
...
}
액세스 조건
액세스 조건은test-and-set-state 방법을 호출하는 라인이 상태를 설정할 수 있는지 여부를 결정합니다.액세스 조건은 일반적으로 동기화기 상태를 기반으로 합니다.거짓 깨우침을 피하기 위해 보통while 순환에 넣는다.접근 조건의 계산 결과는true 또는false입니다.
Lock의 액세스 조건은 isLocked의 값만 간단하게 검사합니다.Bounded Semaphore에서 실제로 두 가지 액세스 조건이 있는 것은 실행 중인 동작이 가져오기 또는 해제 여부에 따라 달라집니다.만약 어떤 라인이 허가를 얻으려면signals 변수가 상한선에 도달했는지 검사합니다.만약 어떤 라인이 허가를 풀려고 한다면,signals 변수가 0인지 확인합니다.
Lock과 Bounded Semaphore에서 온 두 개의 코드 세션이 있는데, 모두 접근 조건이 있습니다.조건이while 순환에서 어떻게 검사되는지 주의해서 관찰하세요.
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
//access condition
while(isLocked){
wait();
}
isLocked = true;
}
...
}
public class BoundedSemaphore {
private int signals = 0;
private int bound = 0;
public BoundedSemaphore(int upperBound){
this.bound = upperBound;
}
public synchronized void take() throws InterruptedException{
//access condition
while(this.signals == bound) wait();
this.signals++;
this.notify();
}
public synchronized void release() throws InterruptedException{
//access condition
while(this.signals == 0) wait();
this.signals--;
this.notify();
}
}
상태 변화
일단 한 라인이 임계 구역에 접근할 수 있는 권한을 얻으면, 동기화기의 상태를 바꾸어 다른 라인이 임계 구역에 들어가는 것을 막아야 한다.다시 말하면, 이 상태는 임계 구역에 라인이 실행 중인 코드를 나타낸다.다른 라인이 임계 구역에 접근하려고 할 때, 이 상태는 접근 조건의 결과에 영향을 주어야 한다.
Lock에서 isLocked=true를 코드로 설정하여 상태를 변경합니다. 신호량에서 상태를 바꾸는 것은signals – 또는signals++입니다.
여기에는 두 개의 상태 변화 코드 세션이 있습니다.
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
//state change
isLocked = true;
}
public synchronized void unlock(){
//state change
isLocked = false;
notify();
}
}
public class BoundedSemaphore {
private int signals = 0;
private int bound = 0;
public BoundedSemaphore(int upperBound){
this.bound = upperBound;
}
public synchronized void take() throws InterruptedException{
while(this.signals == bound) wait();
//state change
this.signals++;
this.notify();
}
public synchronized void release() throws InterruptedException{
while(this.signals == 0) wait();
//state change
this.signals--;
this.notify();
}
}
알림 정책
일단 어떤 스레드가 동기화기의 상태를 바꾸면 다른 대기 스레드의 상태가 바뀌었다는 것을 알려야 할 수도 있습니다.이 상태의 변화가 다른 라인의 접근 조건을true로 바꿀 수도 있기 때문이다.
일반적으로 공지 정책은
알림 대기 루트 중 임의의 것도 간단합니다. notify All () 호출을 notify () 로 바꾸면 됩니다.notify 방법을 사용하면 깨어난 라인이 어떤 라인인지 확인할 수 없습니다. 즉, '대기 라인 중 임의의 라인' 입니다.
때때로 임의의 대기 라인이 아닌 지정한 라인을 알려야 할 수도 있습니다.예를 들어, 만약 라인이 통지되는 순서가 동기화 블록에 들어가는 순서와 일치하도록 보장하거나, 어떤 우선순위의 순서에 따라 통지하려고 한다면.이러한 요구를 실현하려면 모든 대기 라인은 자신의 대상에서wait () 를 호출해야 한다.알림 루틴이 특정한 대기 루틴을 알릴 때, 이 루틴의 자체 대상인 notify () 방법을 사용하면 됩니다.배고픔과 공평함에는 이런 예가 있다.
다음은 공지 정책의 예입니다(대기 스레드를 임의로 공지).
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
//wait strategy - related to notification strategy
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify(); //notification strategy
}
}
Test-and-set 방법
동기화기에서 가장 흔히 볼 수 있는 방법은 두 가지가 있는데 테스트-and-set이 첫 번째(set은 다른 것이다).Test-and-set은 이 방법을 호출한 루틴이 접근 조건을 검사한다는 뜻입니다. 만약 만족한다면, 이 루틴은 동기화기의 내부 상태를 설정해서 접근 권한을 얻었다는 것을 나타냅니다.
상태의 변화는 일반적으로 접근 권한을 얻으려는 다른 라인의 조건 상태를 계산할 때false의 결과를 얻지만, 반드시 그렇지는 않습니다.예를 들어 읽기 자물쇠에서 읽기 자물쇠를 가져오는 루틴은 읽기 자물쇠의 상태를 업데이트해서 읽기 자물쇠를 가져오는 것을 표시하지만, 루틴이 없으면 다른 읽기 자물쇠를 요청하는 루틴도 성공할 수 있다.
테스트-and-set은 원자가 필요합니다. 즉, 어떤 라인이 상태를 검사하고 설정하는 동안 테스트-and-set 방법에서 다른 라인이 실행되는 것을 허용하지 않습니다.
test-and-set 메서드의 프로그램 흐름은 일반적으로 다음 순서를 따릅니다.
필요한 경우 검사 전에 상태 설정
액세스 조건 확인
액세스 조건이 충족되지 않으면 대기 중
액세스 조건이 충족되면 상태를 설정하고 필요할 경우 대기 라인에 통지합니다
다음 ReadWriteLock 클래스의 lockWrite () 방법은test-and-set 방법을 보여 줍니다.lockWrite () 를 호출하는 루틴은 검사하기 전에 상태 (writeRequests++) 를 설정합니다.그런 다음 canGrantWriteAccess()에서 액세스 조건을 확인하고 체크가 통과되면 메소드를 종료하기 전에 내부 상태를 다시 설정합니다.이 방법에는 대기 라인을 알리지 않았다.
public class ReadWriteLock{
private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
private int writeAccesses = 0;
private int writeRequests = 0;
private Thread writingThread = null;
...
public synchronized void lockWrite() throws InterruptedException{
writeRequests++;
Thread callingThread = Thread.currentThread();
while(! canGrantWriteAccess(callingThread)){
wait();
}
writeRequests--;
writeAccesses++;
writingThread = callingThread;
}
...
}
다음 BoundedSemaphore 클래스에는 두 가지test-and-set 방법이 있습니다:take ()와release ().두 방법 모두 내부 상태를 검사하고 설정하는 것이 있다.
소스 코드 인쇄 도움말 보기
public class BoundedSemaphore {
private int signals = 0;
private int bound = 0;
public BoundedSemaphore(int upperBound){
this.bound = upperBound;
}
public synchronized void take() throws InterruptedException{
while(this.signals == bound) wait();
this.signals++;
this.notify();
}
public synchronized void release() throws InterruptedException{
while(this.signals == 0) wait();
this.signals--;
this.notify();
}
}
set 메서드
set 방법은 동기화기에서 흔히 볼 수 있는 두 번째 방법이다.set 방법은 동기화기의 내부 상태를 설정하는 것일 뿐 검사를 먼저 하지 않습니다.set 메서드의 대표적인 예는 Lock 클래스의 unlock() 메서드입니다.자물쇠를 가지고 있는 어떤 라인은 항상 잠금 해제에 성공할 수 있으며, 이 자물쇠가 잠금 해제 상태에 있는지 검사할 필요가 없다.
set 메서드의 프로그램 흐름은 일반적으로 다음과 같습니다.
내부 상태 설정
대기 스레드 알림
다음은 unlock() 방법의 한 예입니다.
public class Lock{
private boolean isLocked = false;
public synchronized void unlock(){
isLocked = false;
notify();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
java 병발 (7) 라인 안전 및 불가변성우리는 변할 수 없는 공유 대상을 만들어서 대상이 온라인 스레드에서 공유될 때 수정되지 않도록 함으로써 스레드 안전을 실현할 수 있다.다음 예는 다음과 같습니다. 이것은 불가변성입니다.하지만 getValue () 방...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.