2010-12-15 2 views
1

두 스레드가 정적 동기화 된 메서드와 비 정적 동기화 된 메서드에 동시에 액세스 할 수 있다는 사실을 확인하기 위해 작성한 아래 테스트의 유효성을 검사하고 싶습니다 (잠금이 다른 개체에 있으므로). 결과가 나오지만 제 해석이 맞는지 아닌지 알고 싶습니다.인스턴스 및 정적 메서드에 대한 동시성 테스트의 유효성

아래 코드를 실행하면 변수 i에 동일한 값이 정적 및 비 정적 방법으로 각각 인쇄되는 것을 보았습니다. 이것은 정적 및 비 정적 메서드가 두 개의 서로 다른 개체에 대한 잠금을 가지며 두 개의 스레드가 동시에 액세스 할 수 있다는 사실을 증명합니다.

코드

import java.util.ArrayList; 
import java.util.List; 

public class TestStaticSynchronize { 

public static final TesteeClass obj = new TesteeClass(); 

/** 
* @param args 
*/ 
public static void main(String[] args) { 
    for(int i = 0; i < 50; i++) { 
     Runner run = new Runner(i); 
     Thread th = new Thread(run); 
     th.start(); 
    } 
} 

static class Runner implements Runnable { 

    private int i; 

    public Runner(int i) { 
     this.i = i; 
    } 

    public void run() { 
     if(i % 2 == 0) { 
      TesteeClass.staticSync(); 
     } else { 
      obj.instanceSync(); 
     } 
    } 

} 
} 

class TesteeClass { 

private static List<Integer> testList = new ArrayList<Integer>(); 


public static synchronized void staticSync() { 
    System.out.println("Reached static synchronized method " + testList.size()); 
    testList.add(1); 
} 

public synchronized void instanceSync() { 
    System.out.println("Reach instance synchronized method " + testList.size()); 
    testList.add(1); 
} 
} 

답변

1

귀하의 평가는 정확합니다. 이유가 여기 있습니다.

그래서 동기화 된 인스턴스 메소드를 가지고의 동등한 동기화 블록 표기를 다시 보자 :

public void instanceSync() { 
    synchronized(this) { 
     System.out.println("..."); 
     testList.add(1); 
    } 
} 

당신이 (즉이) 주변 인스턴스 잠금과 같은 일이 동기화 방법을 쓸 때. 정적 메서드에서는이 매개 변수가 존재하지 않으므로 정적 요소와 동등한 동기화 된 블록은 무엇입니까? 그것은 Class 객체에서 잠그고 있습니다.

public void classSync() { 
    synchronized(TestClass.class) { 
     System.out.println("..."); 
     testList.add(1); 
    } 
} 

따라서이 인스턴스는 TestClass 클래스를 나타내는 개체와 다른 개체입니다. 즉, 두 개의 다른 자물쇠가 사용 중이므로 발견 한 문제가 발생합니다. 결국 테스트 프로그램은 매우 위험하며 스레드로부터 안전하지 않습니다. 인스턴스 메소드는 특히 멀티 스레드 환경에서 사용되는 경우 정적 멤버 기간을 만지지 않아야합니다. 정적 접근법을 통해 액세스를 라우팅해도 괜찮지 만 심각한 버그에서는 직접 액세스가 좋지 않습니다.

둘 다 동일한 객체를 잠그는 방식으로 프로그램을 작성하는 방법이 있지만, 왜 이렇게 코드를 작성하는지 고려하는 것이 중요하다고 생각합니다. 그것은 정말로 많은 장소에서 이와 같은 단일 구조를 공유하기를 원하지만 단일 객체에 대한 참조를 얻는 데 어려움이 있습니까? 이것은 소프트웨어 아키텍처의 핵심이며 다중 스레드 응용 프로그램에서 중요한 역할을합니다. 정적 멤버를 사용하는 것보다 훨씬 좋은 옵션이 있다고 생각합니다. 모든 위치에 참조가있는 단일 인스턴스를 사용하십시오. (잘하면 싱글 톤 패턴, 글로벌 통계 등을 사용하지 마십시오.)

+0

감사합니다. 이런 정적 멤버들과 놀 때의 의미를 이해합니다. 그러나 이것은 행동을 확인하는 가장 좋은 방법 인 것 같습니다. – Fazal

+0

충분히 공정합니다. 만약 당신이 단지이 행동을 보여 주려고한다면 그것은 괜찮습니다. :-) – chubbsondubs

관련 문제