일부 링크에서는 동기화 된 블록 내에서 코드 재정렬이 가능하지만 다른 사이트에서는 가능하지 않습니다. 동기화를 사용할 때 코드 재주문과 관련하여 실제로 발생하는 것을 설명하는 예제를 제공해주십시오.Java에서 동기화 및 코드 재정렬
2
A
답변
4
는 두 가지 reorderings 있습니다 : 이전 또는 동기화 된 블록 (그들은 물론 다른 동기 블록에 있지 제공) 동기화 된 블록 내에서 이동 될 수 있습니다 후
- 문 - 때때로 the "roach motel" principle 라고 동기 블록 내부
- 문 변형 순차적 일관성만큼 재 배열 될 수있다
더 중요하게 : 코드가 제대로 동기화되면 이러한 재정렬은 사용자가 신경 써야하는 프로그램의 실행에 영향을 미치지 않습니다.
예 (모든 변수 원래 0)
Thread1 :
a=1;
synchronized(lock) {
b=1;
c=1;
}
d=1;
Thread2 :
synchronized(lock) {
if (a==1) print(b); // can print 0 or 1
if (b==1) print(a)/print(c); // always prints 1
if (b==1) print(d); // can print 0 or 1
if (d==1) print(a)/print(b)/print(c); // always prints 1
}
특히
, c=1
이전에 d=1
이동 또는 b=1
은 이후에 a=1
이동 스레드 2가 관찰 할 수있는 것이 아니기 때문에 허용됩니다. 동기화 된 b 스레드 1에 의해 실행 된 잠금은 스레드 2에서의 원 자성 연산처럼 보입니다.
반면에 동일한 잠금을 사용하지 않는 스레드는 이러한 순서 변경을 관찰 할 수 있습니다.
2
런타임은 이전 시점을 존중하는 한 작업의 순서를 변경할 수 있습니다. 사양 writes는 :
이 두 가지 작업 사이에 발생-전에 관계의 존재가 반드시 그들이 구현 순서에서 일어날 필요가 있다는 것을 의미하지는 않는다는 점에 유의해야한다. 재주문이 합법적 인 집행과 일치하는 결과를 산출하는 경우, 이는 불법이 아닙니다.
및 구체적
, 두 가지 작업은이 관계-전에 일어난다 공유하는 경우, 그들은 반드시 그들이 일이 공유하지 않는 어떤 코드 순서에서 일어난 것으로 보인다 필요가 없습니다 - 전의 관계. 예를 들어, 다른 스레드의 읽기와 데이터 경쟁중인 한 스레드의 쓰기는 해당 읽기와 순차적으로 발생하는 것처럼 보일 수 있습니다.특히
, 하나 개의 스레드 않는 경우 :
synchronized (lock) {
x = 1;
y = 1;
}
을 다른이하는 이러한 스레드 간의
결코 거기if (y == 1) System.out.println(x);
발생-전에 관계를, 다른 스레드가 y
을 관찰 할 수 있습니다 할당하기 전에 x
이었고, 0을 인쇄하십시오.
답장을 보내 주셔서 감사합니다. 하지만 동기화 된 블록 뒤에 코드가 있다고 가정합니다. 첫 번째 표준에 따라 해당 코드는 동기화 된 블록 내에서 가져올 수 있습니다. 다시 동기화 블록 내의 두 번째 놈 코드는 관계가 위반되기 전에 일어날 때까지 재정렬 될 수 있습니다. 그래서 compliler가 언젠가 블럭 뒤에 나타나는 코드와 함께 동기화 된 블럭 안의 블럭을 재정렬 할 수있는 경우가 아닙니까? – user2392631
블럭에 대해 이야기하는 동안 무엇을 이해하는지 모르겠다.하지만 이론적으로 컴파일러는 동기화 된 블럭 뒤의 코드를 동기화 된 블럭 (블럭 이전이 아닌)의 일부 문장보다 먼저 재정렬 할 수있다. – assylias