2010-06-23 2 views
3

객체 잠금에 혼란이 있습니다. 아래의 클래스는 4 개의 메소드를 가지고 있으며 addB() 메소드는 동기화되어 있습니다.동기화가 객체 잠금을 만듭니다.

내 Scienario에는 4 개의 스레드가 있습니다. 스레드 2가 addB() 메소드에 액세스하면 (Test 객체에 대한 잠금이 생성됩니다), 다른 스레드가 addC() 또는 addD()를 동시에 액세스합니까?

개체 잠금은 한 번에 하나의 스레드 만 허용합니까?

class Test{ 
     private Integer a; 
     private Integer b; 
     private Integer c; 
     private Integer d; 


    public void addA(){ 
     synchronized(a) { 
     a++; 
     } 
    } 
    public synchronized void addB(){ 
     b++; 
     } 

    public void addC(){ 
     c++; 
     } 

    public void addD(){ 
     d++; 
     }  
    } 

EDIT : I 3 개 스레드 (T1, T2 및 T3)를 가지며, 각각이 addB 액세스하려고() ADDC() 및 addD된다(). 스레드 t1이 addB() 메소드에 액세스하면 t2 액세스 addC() 메소드를 동시에 스레드 할 수 있습니까? t2 상태가 아니라면?

class Test{ 
     private Integer a; 
     private Integer b; 
     private Integer c; 
     private Integer d; 


    public void addA(){ 
     synchronized(a) { 
     a++; 
     } 
    } 
    public synchronized void addB(){ 
     b++; 
     } 

    public synchronized void addC(){ 
     c++; 
     } 

    public synchronized void addD(){ 
     d++; 
     }  
    } 
+0

정수는 변경 될 수 없다는 것을 의미합니다. ++를 할 때 실제로 새로운 객체를 만듭니다. 따라서 잠금 장치가 엉망이 될 것입니다. 왜냐하면 a가 삭제되고 값이 새 a에 할당되면 잠금이 손실되기 때문입니다. 이것은 당신의 문제에 도움이되지는 않지만 길 아래의 오류를 해결할 수 있습니다. Integer 대신 int를 사용할 수 있습니다. – Mike

+0

@Mike - 멋진 잡기. 사실,이 특별한 경우에는 오류를 일으킬 수 없다고 생각하지만, 그의 코드가'addA' 구현체에 추가된다면 매우 좋을 것입니다. 또한'int '는 원시적이기 때문에 동기화 할 수 없지만'AtomicInteger'를 사용할 수 있습니다. – danben

+0

@ 단벤 감사합니다. 나는 int 상에 동기화하지 않는다는 것을 몰랐다. 나는 원시적 인 것을 결코 시도한 적이 없다고 생각한다. 당신은 매일 무언가를 배웁니다. – Mike

답변

4

잠금은 실제로 한 번에 하나의 스레드 만 허용하지만 서로 다른 잠금은 서로 영향을주지 않습니다. 당신의 예에서

, 당신은 두 개의 잠금이 - a에 속하는 뮤텍스에 하나, 그리고 (정확하게 게시물에 언급 된대로 synchronized 키워드를 사용할 때 암시 적이다) this에 속하는 뮤텍스 하나.

addB()에 대한 호출은 동기화되지만 다른 메소드 호출은 차단하지 않습니다. 한 스레드가 this에 잠금을 보유하고있는 경우 다른 스레드가 a에 잠금을 유지할 수 있으며 다른 여러 스레드는 addC()addD()을 동시에 실행할 수 있습니다.

: 실제로 Integer으로 작업하는 경우 AtomicInteger 클래스에 대해 자세히 알아볼 수 있습니다. 그들은 당신이 그들 주위의 동기화에 대해 걱정할 필요가 없도록 원자 적 연산을 제공합니다.

+0

다른 스레드가 객체 잠금 상태에서 동기화되지 않은 메서드에 액세스 할 수 있기 때문에 동기가 객체 잠금을 생성한다고 말하면 안됩니다. 나는 아직도 객체 잠금을 의미하는 것이 무엇인지 혼란 스럽다. – Tony

+0

@Thomman : "오브젝트 잠금 상태"에서 무슨 뜻인지 모르겠습니다. Java의 모든 Object에는 고유 한 mutex가 있습니다. Object에서 동기화 할 때 스레드가 synchronized 블록으로 진행하기 전에 보유해야하는 것은이 mutex입니다. – danben

1

코드에 두 개의 잠금이 있습니다. 단 하나의 스레드 만 잠금 # 1 또는 잠금 # 2를 통과 할 수 있습니다. 두 자물쇠는 서로 독립적이므로 스레드를 서로 제외하지 않습니다.

잠금 # 1은 객체에 동기화

public void addA(){ 
     synchronized(a) { 
     a++; 
     } 
    } 

잠금 # 테스트 인스턴스 2를 동기화 (이)

public synchronized void addB(){ 
     b++; 
     } 

ADDC()와 addD()는 그들에 락이에서이 없다 모든 스레드는 동시에 액세스 할 수 있습니다.

1

동기화 된 블록은 "실행 된"개체를 reentrant lock으로 처리하는 환경에 불과합니다. 사실 한 번에 하나의 스레드 만 개체에 대한 잠금을 허용합니다.

메소드 C와 D는 절대로 잠금을 설정하지 않으며 임의의 스레드가 언제든지 실행할 수 있습니다.

그리고 다른 점은 a++을 실행할 때 Integer의 새 인스턴스를 만드는 것입니다.

0

잠금은 스레드를 동기화하는 메커니즘을 제공합니다. 즉, 같은 시점에 하나의 스레드 만 개체의 AddB 메서드에 액세스 할 수 있습니다. 코드 완료 후 잠금을 해제하지 않는 한 다음 코드 반복은 블록에 입력 할 수 없습니다. 스레드

0

잠금 개체의 인스턴스에 따라 사용 예 :

addB() 함수는 다음
public void addB(){ 
    synchronized(this){ 
    //func 
} 
} 
  • 로 rewriten 수 로크 개체에
    class MyClass extends Thread{ 
        Test instanceObj=null;  
        public MyClass(Test obj){ 
         instanceObj=obj; 
        } 
    
        public void run(){ 
         obj.addB(); 
        } 
    } 
    

    함수의 스 니펫에 액세스합니다. 다른 스레드는 다른 기능에 액세스 할 수 있습니다.

  • addA에 대한 잠금 이상은 자체 독립 잠금을 가진 객체 obj.a에 있습니다. 두 개의 다른 스레드가 동시에 addA와 addB에 액세스 할 수 있습니다.
관련 문제