JAVA 다 중 스 레 드. - 부 울 상수 동기 화하 지 마 세 요.

JAVA 에 서 는 synchronized 문 구 를 통 해 다 중 스 레 드 병행 을 실현 할 수 있 습 니 다.동기 코드 블록 을 사용 하면 JVM 은 같은 시간 에 하나의 스 레 드 만 대상 의 자 물 쇠 를 가 질 수 있 도록 보장 합 니 다.자물쇠 메커니즘 은 여러 개의 라인 이 안전하게 임계 자원 에 접근 하 는 것 을 실현 했다.
 
동기 코드 작성 방법 은 다음 과 같 습 니 다.
 
코드 1:
Object obj = new Object();
...
synchronized(obj) {
  //TODO:       
}
 
 
JAVA 의 다 중 스 레 드 는 항상 함정 으로 가득 차 있 습 니 다. 만약 에 우리 가 Boolean 을 동기 화 대상 으로 한다 면 다음 과 같은 두 가지 상황 이 발생 할 수 있 습 니 다.
 
1. 한 대상 에 자 물 쇠 를 채 우 고 실제 동기 화 하 는 것 은 서로 다른 대상 이 라 고 생각 합 니 다.
 
코드 2:
 
private volatile Boolean isTrue = false;

publich void aMethod() {
  ...
  synchronized(isTrue) {
    isTrue = !isTrue;
    //TODO:       
    isTrue = !isTrue;
  }
  ...
}

 위의 코드 를 보면 문제 가 없습니다. synchronized (isTrue) 를 사용 하여 같은 시간 에 하나의 스 레 드 만 임계 자원 에 접근 할 수 있 기 때 문 입 니 다. 그러나 사실은 그렇지 않 습 니 다.false 와 true 라 는 두 상수 가 서로 다른 대상 에 대응 하기 때문이다.isTrue 가 변화 할 때 서로 다른 스 레 드 가 서로 다른 대상 을 동기 화 할 수 있 습 니 다.JAVA 의 자동 포장 은 false 를 Boolean. FALSE 로, true 를 Boolean. TRUE 로 변경 합 니 다.이상 의 상황 을 기록 하 는 테스트 코드 는 다음 과 같 습 니 다.
 
코드 3:
 
public class BooleanTest {
	
	private volatile Boolean isTrue = Boolean.FALSE; //   false   
	
	public void aMethod() {
		for(int i=0;i<10;i++) {
			Thread t = new Thread() {
				public void run() {
					synchronized(isTrue) {
						isTrue = !isTrue;
						System.out.println(Thread.currentThread().getName() + " - isTrue=" + isTrue);
						try{
							Double ran = 1000 * Math.random();
							Thread.sleep(ran.intValue());
						}catch(InterruptedException e) {}
						
						if(!isTrue) System.out.println(Thread.currentThread().getName() + " - Oh, No!");

						isTrue = !isTrue;
					}
				}
			};
			t.start();
		}
	}
	
	public static void main(String... args) {
		BooleanTest bt = new BooleanTest();
		bt.aMethod();
	}
}

 상기 코드 를 실행 하면 "- Oh, No!"를 자주 볼 수 있 습 니 다. 서로 다른 스 레 드 가 synchronized 코드 블록 에 동시에 들 어 가 는 것 을 의미 합 니 다.
 
2. 동기 화 된 것 이 서로 다른 대상 이 라 고 생각 하고 실제 적 으로 대상 이다.
 
때때로 우 리 는 여러 대상 에서 동기 화 를 원 할 수도 있다. 만약 에 Boolean 을 동기 화 대상 으로 사용한다 면 원래 관계 가 없어 야 할 두 동기 블록 이 같은 대상 의 자 물 쇠 를 사용 하 게 될 수도 있다.예 는 다음 과 같다.
 
코드 4:
 
private volatile Boolean aBoolean = Boolean.FALSE;

private volatile Boolean anotherBoolean = false;

public void aMethod() {
  ...
  synchronized(aBoolean) {
    //TODO:       1
  }
  ...
}

public void anotherMethod() {
  ...
  synchronized(anotherBoolean) {
    //TODO:       2
  }
  ...
}

 원래 aMethod 와 anotherMethod 가 각각 두 조 의 관계 가 없 는 스 레 드 로 호출 된다 고 가정 합 니 다.그러나 Boolean. FALSE 와 false 가 같은 대상 을 가리 키 기 때문에 임계 자원 2 에 대한 접근 이 임계 자원 1 에 의 해 막 힐 수 있 습 니 다 (반대로 도 마찬가지 입 니 다).
 
상기 두 가지 상황 은 동기 블록 을 사용 할 때 가능 한 한 Boolean 대상 을 동기 화 대상 으로 사용 하지 않 아 도 된다 는 것 을 설명 한다. 그렇지 않 으 면 예상 치 못 한 문제 가 발생 하거나 향후 코드 수정 에 함정 을 초래 할 수 있다.
 
이 를 통 해 알 수 있 듯 이 상수 에 대한 동기 화 는 모두 위험 하 다.부 울 린 을 동기 화 하려 면 new 연산 자 를 사용 하여 부 울 린 대상 을 만들어 야 합 니 다.

좋은 웹페이지 즐겨찾기