2016-10-13 3 views
0

:필드 잠금 자바

public class SomeClass extends Thread { 
    ... 
    private double a; 
    private double b; 

    private double increaseVal; 

    public void setIncreaseVal(double increaseVal) { 
     this.increaseVal = increaseVal; 
    } 

    private void updateAB() { 
     ... 
     // Computing the new a and b values 
     a = ... * increaseVal; 
     b = ... * increaseVal; 
     ... 
    }  

    @Override 
    public void run() { 
     try { 
      ...     
      updateAB(); 
      Thread.sleep(500); 
     } 
     ... 
    } 
} 

public class OtherClass { 
    ... 
    private HashMap<String, SomeClass> someClasses; 

    private void setIncreaseValue(String id, double value){ 
     ... 
     someClasses.get(id).setIncreaseValue(value); 
     ... 
    } 
} 

increaseValSomeClassupdateAB 방법 등이 처리 될 때 동일한 increaseVal 값이 이용되는 경우 모두 ab 필드를 잠그는 것이 가능 업데이트 되었습니까?

setIncreaseValueOtherClass 인 경우 a이 업데이트 된 후 increaseVal의 값을 변경할 수 있습니다. b이 업데이트되면이 방식으로 increaseVal의 새 값이 사용됩니다. 나는 그것을 피하고 싶습니다.

ab 값을 업데이트하기 전에 synchronized(this)을 입력하면 제대로 작동합니까? 이처럼

:

synchronized(this) { 
    // Computing the new a and b values 
    a = ... * increaseVal; 
    b = ... * increaseVal; 
} 

감사합니다!

답변

0

스레드 안전 코드를 올바르게 구현하려면 먼저 스레드 안전성을 유지해야하는 클래스의 상태를 식별해야합니다. 은 당신의 예에서 상태 (즉, 모두가 읽기 및 쓰기) 상태에 대한 액세스가 같은 잠금 개체를 사용하여 동기화 다음 단계는 모든 있는지 확인하는 것입니다 세 개의 필드

private double a; 
private double b; 
private double increaseVal; 

으로 표시됩니다. 당신의 예에서

이 쉽게 setIncreaseVal(...)updateAB() 방법에 동기화 된 키워드를 추가 한 후 잠금으로 this를 사용하여 구현할 수 있습니다

public synchronized void setIncreaseVal(double increaseVal) { 
    ... 
} 

private synchronized void updateAB() { 
    ... 
} 

이것은 코드 스레드 안전을 만들 것입니다 : ab 항상 것입니다 increaseVal을 사용하여 업데이트하십시오. 다른 스레드가 updateAB()를 실행하는 등 같은 increaseVal 업데이트로 클라이언트 코드가 ab를 사용한다는 보장은 없지만 그러나 코드는 a 읽 및 b 여전히 ab을 읽을 수 있습니다 : 이것은 당신이 필요로하는 경우 , ab에 대한 액세스를 동기화해야합니다 (코드는 예제에 표시되지 않으므로 이에 대해서는별로 말할 수 없습니다). updateAB()의 동기화에 관해서는

: 사용하지 않는 방법에있어서 많은 코드가있는 경우 a, bincreaseVal하고 실행하는 데 시간이 오래 걸릴 수 있습니다 (예를 들어,

private void updateAB() { 
    ... 
    synchronized(this) { 
     // Computing the new a and b values 
     a = ... * increaseVal; 
     b = ... * increaseVal; 
    } 
    ... 
} 
+0

주셔서 감사합니다 유용한 정보 코포에 대한 많은 : I/O 작업, DB와 같은 액세스)의 다음 전체 방법보다는 a, bincreaseVal를 사용하는 경우에만 코드를 동기화하는 의미가 있기 때문이다. 당신이 내 마음에 들지 않는다면, 나는 멀티 스레딩에 대해 약간 새로운 것처럼, '이'모양보다 다른 무엇이 잠금 상태일까요? 또는'a','b' 및'increaseVal'에 대해서만 특정 잠금을 만드는 것이 어떻게 가능합니까? – Mihai

+0

당신은 대단히 환영합니다. 모든 오브젝트는 잠금으로 사용할 수 있습니다. 예를 들어,이 객체를 다음과 같이 클래스의 필드로 정의 할 수 있습니다 :'private Object aLock = new Object();'그리고 동기화 된 블록에서 사용 :'synchronized (aLock) {...}'. 다른 잠금을 사용하고 코드가 잘 설계되지 않은 경우 스레드가 안전하지 않거나 교착 상태가 발생할 수 있음을 유의하십시오. –

0

increaseVal을 우려 할 경우 대신 increaseVal을 잠글 수 있습니다. 즉

synchronized(increaseVal) { 
    // Computing the new a and b values 
    a = ... * increaseVal; 
    b = ... * increaseVal; 
} 
0

는 AtomicInteger로 increaseVal을 확인합니다. 원자화하면 문제를 해결할 수 있습니다.