자바 스 레 드 통신 및 스 레 드 허위 각성 지식 총화
스 레 드 가 내부 에서 실 행 될 때 스 레 드 스케줄 은 일정한 투명 성 을 가지 고 프로그램 은 스 레 드 의 교대 집행 을 제어 할 수 없습니다.그러나 자바 자 체 는 스 레 드 의 조화 로 운 운행 을 보장 하 는 메커니즘 을 제공 했다.
현재 시스템 에 두 개의 라인 이 있다 고 가정 하면 각각 예금 과 인출 을 대표 한다.돈 을 저금 하면 바로 꺼 내 서 지 정 된 계좌 로 옮긴다.이것 은 스 레 드 간 의 협력 과 관련 되 어 있 습 니 다.Object 류 가 제공 하 는 wait(),notify(),notify All()세 가지 방법 을 사용 합 니 다.Thread 류 에 속 하지 않 고 Object 에 속 합 니 다.이 세 가지 방법 은 모니터 대상 에서 호출 해 야 합 니 다.
wait():현재 스 레 드 대기,현재 대상 잠 금 해제,다른 스 레 드 가 notify 또는 notify All 을 사용 하여 이 스 레 드 를 깨 울 때 까지 CPU 를 양보 합 니 다4.567917.notify():이 동기 모니터 에서 기다 리 는 단일 스 레 드 를 깨 우 고 여러 스 레 드 가 존재 하면 무 작위 로 하 나 를 깨 웁 니 다.notify 를 실행 하면 바로 자 물 쇠 를 풀 지 않 습 니 다.synchronized 코드 블록 을 완전히 종료 하거나 도중에 wait 를 만 나 야 wait 상태의 스 레 드 가 이 대상 의 자 물 쇠 를 쟁취 할 수 있 습 니 다4.567917.notify All():이 동기 모니터 의 모든 스 레 드 를 깨 웁 니 다지금 은 두 가지 동기 화 방법 으로 각각 돈 을 저금 하고 돈 을 찾 는 것 을 대표 한다.
4.567917.잔액 이 0 일 때 저금 절차 에 들 어가 저금 작업 을 한 후에 돈 을 찾 는 스 레 드 를 깨 웁 니 다
/**
*
*
* @throws InterruptedException
*/
public synchronized void increase() throws InterruptedException {
// 1, , 。
if (num == 1) {
this.wait();
}
//
num++;
System.out.println(Thread.currentThread().getName() + ":num=" + num);
//
this.notifyAll();
}
/**
*
*
* @throws InterruptedException
*/
public synchronized void decrease() throws InterruptedException {
// 0, , 。
if (num == 0) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + ":num=" + num);
this.notifyAll();
}
호출 방법:
private int num = 0;
public static void main(String[] args) {
Test test = new Test();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.increase();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " ").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.decrease();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " ").start();
}
결 과 는 아무 문제 가 없 었 다. 스 레 드 거짓 각성
이 같은 스 레 드 통신 은 별 문제 가 없 는 것 처럼 보이 지만,이때 예금 과 돈 을 찾 는 사람 수 를 각각 1 씩 늘 리 고 운행 결 과 를 보면 된다.
private int num = 0;
public static void main(String[] args) {
Test test = new Test();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.increase();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " 1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.decrease();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " 1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.increase();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " 2").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
test.decrease();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, " 2").start();
}
생 긴 결 과 는 이미 최초의 것 이 아니 라 0 과 1 만 있 었 다.이 결 과 를 초래 한 원인 은 바로 스 레 드 간 의 허위 각성 이다.
현재 각각 여러 개의 인출 과 예금 라인 이 있 기 때문이다.만약 에 그 중의 한 저금 스 레 드 가 실 행 된 후에 wait 를 사용 하여 동기 모니터 를 잠 그 면 나머지 여러 개의 인출 스 레 드 는 동시에 깨 어 날 것 이다.이때 잔액 은 1 이 고 10 개가 동시에 돈 을 찾 으 면 잔액 은-9 로 변 하여 결과 가 잘못 될 것 이다.
따라서,매번 스 레 드 가 wait 에서 깨 어 날 때마다,깨 우기 조건 에 부합 되 는 지 다시 테스트 해 야 하 며,부합 되 지 않 으 면 계속 기 다 려 야 합 니 다.
여러 스 레 드 가 동시에 깨 어 나 서 if(xxxx){wait();}처 if 판단 은 한 번 만 실 행 됩 니 다.현재 깨 어 난 스 레 드 가 왔 을 때 if 가 판단 되 었 기 때문에 wait 뒤의 구문 에서 계속 실 행 됩 니 다.따라서 if 를 while 로 바 꾸 면 이 문 제 를 해결 할 수 있 습 니 다.다음 에 깨 어 난 스 레 드 가 왔 습 니 다.while 다시 판단 해 보 니 깨 어 난 스 레 드 가 잠 겨 있 습 니 다.따라서 이 거짓 으로 깨 어 난 스 레 드 는 자 물 쇠 를 계속 기다 릴 것 이다.
/**
*
*
* @throws InterruptedException
*/
public synchronized void increase() throws InterruptedException {
while (num == 1) {// , while
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + ":num=" + num);
this.notifyAll();
}
/**
*
*
* @throws InterruptedException
*/
public synchronized void decrease() throws InterruptedException {
while (num == 0) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + ":num=" + num);
this.notifyAll();
}
다시 실행,결과 정상:자바 스 레 드 통신 및 스 레 드 허위 깨 우기 지식 총화 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 스 레 드 통신 및 스 레 드 허위 깨 우기 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 지원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.