2016-06-27 4 views
5

스레드 안전이 Java의 멤버 매개 변수를 처리 할 때 이미 역할을하는지 알고 싶습니다. Java에서 메서드 매개 변수의 스레드 안전

은 당신이 API

boolean moreThanTen(long value) { 
    if(value > 10) return true; 
    else return false; 
} 

이 방법은 스레드 안전 할 것입니다 방법을 말해봐?

모든 스레드는 로컬 변수에 대해 자체 스택을 가지고 있기 때문에 상상할 수 있습니다. 그리고 프리미티브는 모두이 로컬 스택에 저장됩니다.

확실하지 않은 유일한 이유는 long이 두 개의 별도 읽기이므로 일반적으로 스레드로부터 안전하지 않다는 것입니다.

제 질문은 : 메소드의 매개 변수가 원자 적으로 복사되는지 확인할 수 있습니까? 따라서 프리미티브를 매개 변수로 사용하는 경우 (심지어 float/long) 로컬 변수 스레드 안전성에 복사하는 동안 문제가되지 않을 수 있습니까?

감사합니다.

+3

변경 가능한 상태가 없으면 메서드가 스레드로부터 안전함을 의미합니다. – Andreas

답변

8

스레드가 안전하지 않게하려면 메소드가 둘 이상의 스레드가 공유 리소스 (예 : 필드)에 액세스하도록 허용해야합니다.

예에서 공유 리소스가 없으므로 (값으로 java가 인수를 전달하므로) 메소드가 안전하지 않을 수 있습니다. threshold 하나 개 이상의 스레드에서 액세스 할 수 있으며 올바르게 동기화되지 않은 변수에 액세스하기 때문에

이 하나가 안전하지 않은 것 : 그것은 다른 스레드에 의해 업데이트되는 동안

  • 스레드가 threshold 변수를 읽을 수있다, 일관성없는 읽기 (long writes are not guaranteed to be atomic)가 발생할 수 있습니다. 및
  • 하나의 스레드에서 변수 threshold에 대한 쓰기가 동기화되지 않아 다른 스레드에서 보이지 않을 수 있으며, 이로 인해 두 번째 스레드가 부실 값을 읽게 될 수 있습니다. 이 경우 스레딩의
private long threshold; //mutable, may change 

boolean moreThanThreshold(long value) { 
    return value > threshold; //side comment: cleaner than your if/else 
} 
void setThreshold(long t) { this.threshold = t; } 
+0

귀하의 예제는 개별 읽기 및 쓰기가 원자 적이기 때문에 스레드로부터 안전합니다. 휘발성을 사용하여 해결할 수있는 가시성 문제를 보여주었습니다. 이는 휘발성을 사용하여 단어 찢김을 제거합니다 (JLS 호환 JVM에서). – xTrollxDudex

+0

가시성 문제가있는 경우 정의에 따라 메소드가 스레드 안전하지 않습니다. 게다가, 긴 기입은 JLS에 의해 원자 적이라고 보증되지 않습니다. – assylias

+0

* volatile * long 쓰기는 – xTrollxDudex

1

어떤 문제가 .. 모든 방법 자신의 스택에서 발생하지 않습니다 읽습니다. 간단히 말해서 그들은 두 개의 읽기가 있지만 그들은 다른 스레드간에 공유되지 않는 스택 내부의 값에서 발생합니다.

두 가지 읽기가 문제가되지 않는 이유에 대해 자세히 설명합니다.

메소드에 인수를 전달할 때 참조 변수는 전달하지 않지만 참조 변수는 해당 비트의 사본을 전달합니다. 다음과 같은 것 : 3bad086a. 3bad086a는 전달 된 객체에 도달하는 방법을 나타냅니다. 그래서 우리는 참조의 가치라는 것을 3bad086a에 전달합니다. 참조 자체가 아닌 참조 값을 전달합니다 (객체가 아닙니다). 이 값은 실제로 COPIED되어 메소드에 주어집니다. 우리는 항상 참조 값의 비트를 복사합니다. 기본 데이터 형식 인 경우이 비트는 기본 데이터 형식 자체의 값을 포함합니다. 오브젝트의 경우, 비트는 JVM에 오브젝트에 도달하는 방법을 알려주는 주소 값을 포함합니다.