2010-06-28 6 views
6

당신이 synchronized 키워드로 선언 한 단 하나의 스레드에 의해 실행될 메서드를 잠글 때를 알고 있습니다.synchronized를 사용하여 전체 클래스에 대한 메서드를 잠그는 방법은 무엇입니까?

클래스의 경우 스레드 이 해당 클래스의 인스턴스에서 일부 코드를 실행 중일 때 객체 클래스 전체에 잠금을 제공하는 방법은 무엇입니까?

즉, 스레드가 개체의 메서드를 실행할 때 다른 스레드는 같은 클래스의 다른 인스턴스에서도 같은 메서드를 실행할 수 없습니다.

+1

왜 이렇게해야하는지 설명 할 수 있습니까? 나는 당신이 잘못된 문제를 공격하고 있다는 느낌을 가지고 있습니다. 실제 문제가 다른 곳에서와 같이 * 완전히 다른 클래스 인스턴스에서 메소드 호출을 동기화해야합니다. –

답변

8

당신은 특정 개체에 대한 몇 가지 지정된 정적 락 객체, 또는 (정적 방법은 동기화 할 선언 할 때 발생) 클래스 객체 중 하나를 동기화 :

class X { 
    private static final Object lock = new Object(); 
    public void oneAtATime() { 
     synchronized (lock) { 
      // Do stuff 
     } 
    } 
} 
class Y { 
    public void oneAtATime() { 
     synchronized (Y.class) { 
      // Do stuff 
     } 
    } 
} 

각 변형이 자신의 장단점이 있습니다를 ; 클래스를 잠그면 클래스 외부의 다른 코드가 자물쇠를 사용하여이를 금지하는 자체적 인 이유 (사용자가 제공하는 것보다 더 높은 수준의 동기화를 조정할 수 있음)에 대해 동일한 잠금을 사용할 수 있습니다. static final Object lock 접근 방식을 사용하면 잠금 private 필드 (잠금을 추론하는 것이 더 쉬워지고 다른 사람이 잘못된 코드를 작성했기 때문에 교착 상태에서 코드를 피할 수 있습니다).

당신은 물론 또한 잠금 (및 ReentrantLock 것은 현재 높은 경쟁에서 암시 잠금보다 조금 더 나은 수행)을 통해 더 많은 제어를 제공 명시 적 Lock들처럼, java.util.concurrent 일부 동기화 메커니즘을 사용할 수 있습니다. 그것을 만들기에서 어떤 옆으로 지금까지 본질적으로 다른 모든 인스턴스에 연결됩니다 만든 클래스의 모든 인스턴스 (의미 - 정적/글로벌 잠금이 갈 수있는 좋은 방법이 아니라는 것을 참고 : 편집


코드를 테스트하거나 읽는 것이 더 어려우므로 확장성에 심각한 영향을 미칠 수 있음). 나는 어떤 종류의 세계적인 상태를 동기화하기 위해 이것을한다고 가정합니까? 이 경우 전역/정적 상태를 대신 클래스로 래핑하고 전역으로 동기화하지 않고 인스턴스별로 동기화를 구현하는 방법을 고려해 보겠습니다.대신에 이런 일의

:

class Z { 
    private static int state; 
    public void oneAtATime(){ 
     synchronized (Z.class) { 
      state++; 
     } 
    } 
} 

이처럼 수행

class State { 
    private int value; 
    public synchronized void mutate(){ value++; } 
} 
class Z { 
    private final State state; 
    public Z(State state){ 
     this.state = state; 
    } 
    public void oneAtATime(){ 
     state.mutate(); 
    } 
} 
// Usage: 
State s1 = new State(), s2 = new State(); 
Z foo = new Z(s1); 
Z bar = new Z(s1); 
Z frob = new Z(s2); 
Z quux = new Z(s2); 

이제 foobar는 여전히 서로 연결되어 있지만 frobquux에서 독립적으로 작업 할 수 있습니다. 정적 클래스의 필드 또는 클래스 자체에

+0

이 (마지막) 방법은 나가 말할 것입니다 거의 확실히 확실하다. 클래스의 하위 클래스와 프로그램의 여러 인스턴스에서 발생해야하는 사항과 정적 메서드가 필요할 때주의해야 할 사항을 투명하게 만듭니다. –

2

해당 방법 내에서 정적 Mutex을 사용할 수 있습니다. 따라서 어떤 동시 스레드가 메소드 내부에서 블로킹하고있는 동안 다른 스레드는 자신이 속한 클래스의 어떤 오브젝트에 상관없이이를 실행합니다. synchronized과 같은 효과를 내기위한 특별한 하나의 키워드가 있다고 생각하지 않습니다.

다소 적극적인 동기화이므로 최대한 피할 것입니다.

0

이에 대한 기본 제공 메커니즘이 없습니다. 자신 만의 정적 잠금 속성을 만들고 모든 메소드에서 잠금 및 잠금 해제를 확인하십시오. 예외를 잊지 말고 "finally"섹션에서 잠금을 해제하십시오.

5

정적 동기화 된 메서드를 사용하는 경우 클래스 잠금을 통해 잠 깁니다. 또한 클래스의 정적 객체를 선언하고 나는 같은 것을 통해 생각하는 방법에 그것을 잠글 수 있습니다 :이 작업을해야

private static final Object STATIC_LOCK = new Object(); 

private void foo() { 
    synchronized (STATIC_LOCK) { 
      //do stuff... 
    } 
} 
0

:

public class MyClass { 
    void synchronizedMethod() { 
    synchronized (MyClass.class) { 
     // synchronized on static level 
    } 
    } 
} 

을 어떤 'missuses'클래스의 런타임 표현 잠금. 이는 Java에서 임의의 객체를 뮤텍스로 사용할 수 있기 때문에 가능합니다.

+0

정적 동기화 된 메서드가 클래스 개체와 동기화되는 것을 감안할 때 오용을하는 이유는 무엇입니까? –

+0

그래? 이 경우 Java 디자이너가 그런 식으로 작업한다면 아마도 사용하지 않을 것입니다. 나는 가장 깨끗한 방법은 전용 static Monitor/Mutex 객체를 가지고 있다고 생각했다. 그리고 어떤 객체를 사용하는 것은 다소 해킹이다 - 비록 내가 개인적으로 그 옵션을 직접 선택할지라도. 지금 따옴표 안에 missuse를 넣으십시오 :) –

2

동기화 :

synchronized(MyClass.class) { 
     // mutually excluded method body 
} 
1

두 스레드가

public void someMethod() { 
    synchronized(ClassThatShouldBeProtected.class) { 
    someSynchronizedCode(); 
    } 
} 

이 방식의 장점 사실이 공사를 사용해야은, 그 클래스 자체가 목적입니다 따라서 모니터가 있습니다. 그런 다음 인위적인 정적 인스턴스가 필요하지 않습니다. 그것을 달성하기 위해 여러 가지 방법에 대한

0

http://www.janeg.ca/scjp/threads/synchronization.html

회담. 일반적으로 잠금 장치는 금지되어 있으며 스레딩의 이점을 방해합니다. 따라서 중요한 코드는 가능한 한 최소화해야합니다.

클래스 레버 잠금을 사용하여 클래스의 정적 변수에 액세스하거나 클래스의 공통 외부 리소스에 대한 액세스를 보호합니까? 이 경우 액세스하는 동안 별도의 잠금 장치가 있어야합니다.

관련 문제