자바 병렬 프로 그래 밍 대상 발표(Publish)와 일출(Escape)
2387 단어 자바 병렬 프로 그래 밍
대상 이 현재 범위 밖의 코드 에 사 용 될 수 있 도록 합 니 다.
예시:
@Slf4j
public class UnsafePublish {
private String[] states = {"a", "b", "c"};
public String[] getStates() {
return states;
}
public static void main(String[] args) {
UnsafePublish unsafePublish = new UnsafePublish();
log.info("{}", Arrays.toString(unsafePublish.getStates()));
unsafePublish.getStates()[0] = "d";
log.info("{}", Arrays.toString(unsafePublish.getStates()));
}
}
Public 접근 단 계 를 통 해 클래스 의 도 메 인(states)을 발 표 했 습 니 다.클래스 의 모든 외부 스 레 드 에서 이 도 메 인 에 접근 할 수 있 습 니 다.이러한 발표 대상 은 안전 하지 않 습 니 다.다른 스 레 드 가 이 도 메 인 을 수정 할 지 모 르 기 때 문 입 니 다.쉽게 말 하면 unsafePublish 를 통 해 이러한 인 스 턴 스 를 발 표 했 습 니 다.
대상 일출 이란 무엇 인가?
잘못된 발표대상 이 아직 구조 가 완성 되 지 않 았 을 때 다른 스 레 드 에 의 해 보 입 니 다.
예시:
@Slf4j
public class Escape {
private int thisCanBeEscape = 0;
public Escape () {
new InnerClass();
}
private class InnerClass {
public InnerClass() {
log.info("{}", Escape.this.thisCanBeEscape);
}
}
public static void main(String[] args) {
new Escape();
}
}
Escape 류 의 구조 방법 은 아직 구조 가 완성 되 지 않 았 기 때문에 내부 류 인 InnerClass 는 이러한 대상 의 인용 을 얻 을 수 있 고 이 를 대상 일출 이 라 고 부른다.
또 다른 탈출 을 본다.
public class Escape {
private int id = 0;
private String name = null;
public Escape() {
new Thread(new MyRun()).start();
new Thread(new MyRun()).start();
name = "zhangsan";
}
private class MyRun implements Runnable {
@Override
public void run() {
System.out.println(Escape.this.name);
System.out.println(Escape.this.id);
}
}
public static void main(String[] args) {
new Escape();
}
Escape 구조 방법 에 서 는 이러한 속성 name 의 값 을 zhangsan 으로 초기 화 하려 고 했 으 나 구조 방법 에서 스 레 드 를 시작 하기 때문에 name="zhangsan"이 실행 되 지 않 았 을 수도 있 습 니 다.스 레 드 에서 name 의 값 은 null 값 입 니 다.
해결 방법:
구조 함수 가 실행 되 기 전에 Object.this 라 는 인용 을 피하 고 구조 함수 에서 스 레 드 를 시작 하지 않도록 해 야 합 니 다.
안전하게 발표 하 는 네 가지 방식:
4