2013-09-21 3 views
2

일부 링크에서는 동기화 된 블록 내에서 코드 재정렬이 가능하지만 다른 사이트에서는 가능하지 않습니다. 동기화를 사용할 때 코드 재주문과 관련하여 실제로 발생하는 것을 설명하는 예제를 제공해주십시오.Java에서 동기화 및 코드 재정렬

답변

4

는 두 가지 reorderings 있습니다 : 이전 또는 동기화 된 블록 (그들은 물론 다른 동기 블록에 있지 제공) 동기화 된 블록 내에서 이동 될 수 있습니다 후

,536,913 (즉, 효력이 일어나도 이전 블록과의 관계를 공유하는 다른 코드에서 볼 수 없음)

더 중요하게 : 코드가 제대로 동기화되면 이러한 재정렬은 사용자가 신경 써야하는 프로그램의 실행에 영향을 미치지 않습니다.

예 (모든 변수 원래 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에서의 원 자성 연산처럼 보입니다.

반면에 동일한 잠금을 사용하지 않는 스레드는 이러한 순서 변경을 관찰 할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 하지만 동기화 된 블록 뒤에 코드가 있다고 가정합니다. 첫 번째 표준에 따라 해당 코드는 동기화 된 블록 내에서 가져올 수 있습니다. 다시 동기화 블록 내의 두 번째 놈 코드는 관계가 위반되기 전에 일어날 때까지 재정렬 될 수 있습니다. 그래서 compliler가 언젠가 블럭 뒤에 나타나는 코드와 함께 동기화 된 블럭 안의 블럭을 재정렬 할 수있는 경우가 아닙니까? – user2392631

+0

블럭에 대해 이야기하는 동안 무엇을 이해하는지 모르겠다.하지만 이론적으로 컴파일러는 동기화 된 블럭 뒤의 코드를 동기화 된 블럭 (블럭 이전이 아닌)의 일부 문장보다 먼저 재정렬 할 수있다. – assylias

2

런타임은 이전 시점을 존중하는 한 작업의 순서를 변경할 수 있습니다. 사양 writes는 :

이 두 가지 작업 사이에 발생-전에 관계의 존재가 반드시 그들이 구현 순서에서 일어날 필요가 있다는 것을 의미하지는 않는다는 점에 유의해야한다. 재주문이 합법적 인 집행과 일치하는 결과를 산출하는 경우, 이는 불법이 아닙니다.

및 구체적

, 두 가지 작업은이 관계-전에 일어난다 공유하는 경우, 그들은 반드시 그들이 일이 공유하지 않는 어떤 코드 순서에서 일어난 것으로 보인다 필요가 없습니다 - 전의 관계. 예를 들어, 다른 스레드의 읽기와 데이터 경쟁중인 한 스레드의 쓰기는 해당 읽기와 순차적으로 발생하는 것처럼 보일 수 있습니다.특히

, 하나 개의 스레드 않는 경우 :

synchronized (lock) { 
    x = 1; 
    y = 1; 
} 

을 다른이하는 이러한 스레드 간의

결코 거기
if (y == 1) System.out.println(x); 

발생-전에 관계를, 다른 스레드가 y을 관찰 할 수 있습니다 할당하기 전에 x이었고, 0을 인쇄하십시오.