2017-10-24 3 views
0

2 개의 스레드가 있고이 스레드로 Student 개체의 다른 메서드를 실행하려고합니다. 문제는이 코드를 실행하면 t2 스레드가 동기화 된 블록을 완료하기 위해 t1을 기다리는 것입니다.다른 방법으로 다른 개체를 잠그는 방법은 무엇입니까?

t1이 완료 될 때까지 기다리는 이유는 무엇입니까? 어떻게 서로를 차단하지 않고 다른 방법으로 다른 객체를 잠글 수 있습니까?

주요 방법은 다음과 같습니다.

Student student = new Student(); 
Thread t1 = new Thread(() -> { 
    try { 
     student.addA(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
    } 
}); 

Thread t2 = new Thread(() -> { 
    try { 
     student.addB(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
    } 
}); 

t1.start(); 
t2.start(); 

여기는 학생 수업입니다.

public class Student { 

    private Integer a = 0; 
    private Integer b = 0; 

    public void addA() throws InterruptedException{ 
     System.out.println("addA start"); 
     synchronized(a){ 
      System.out.println("addA sync start"); 
      a++; 
      Thread.sleep(5000); 
     } 
     System.out.println("addA end"); 
    } 

    public void addB() throws InterruptedException{ 
     System.out.println("addB start"); 
     synchronized(b){ 
      System.out.println("addB sync start"); 
      b++; 
      Thread.sleep(5000); 
     } 
     System.out.println("addB end"); 
    } 

} 

답변

5

이 :

private Integer a = Integer.valueOf(0); 
private Integer b = Integer.valueOf(0); 

the result of Integer.valueOf(0) is cached, 그래서 당신은 실제로 같은 객체를 동기화하고 있습니다 :

private Integer a = 0; 
private Integer b = 0; 

실제로이 동일합니다.

new Integer(0)을 사용하면 다른 Integer 인스턴스를 얻을 수 있습니다.

그러나 이것은 단지 길 아래 문제 중 하나 반복 걷어차는 :

a++; 

는 실제로 :

a = Integer.valueOf(a.intValue() + 1); 

은 그래서 당신은 잠재적으로 적어도 a 때까지, 다시 같은 문제로 실행할 수 있습니다 ' s 값이 Integer.valueOf 메소드로 캐시 된 값의 범위를 초과합니다 (최소 127이지만 구현에 따라 다름). 바로이 라인이 실행 된 것처럼, 다른 스레드가 동기화 블록을 입력 할 수 있기 때문에,

a = new Integer(a.intValue() + 1); 

그러나, 변경 가능한 기준에 동기화하는 것은 매우 나쁜 생각은 다음과 같습니다

동일한 트릭을 적용 할 수 있습니다 . (이미 입력을 차단 한 항목이 아니라 나중에 synchronized에 도달하는 모든 스레드).

private final Object aLock = new Object(); 
private final Object bLock = new Object(); 

대신에 상응 ab 이러한에 동기화 :

대신 ab의 각각에 대해 별도의 잠금 객체를 생성해야합니다.

관련 문제