programing

"volatile" 키워드는 무엇에 사용됩니까?

goodsources 2023. 2. 2. 21:11
반응형

"volatile" 키워드는 무엇에 사용됩니까?

제가 기사를 좀 읽었는데volatile키워드를 입력했는데 정확한 용도를 찾을 수 없었습니다.C#과 Java에서 어떤 용도로 사용해야 하는지 알려주시겠습니까?

다음 예를 생각해 보겠습니다.

int i = 5;
System.out.println(i);

컴파일러는 이것을 최적화하여 5를 인쇄하는 경우가 있습니다.

System.out.println(5);

단, 변경할 수 있는 다른 스레드가 있는 경우i이것은 잘못된 행동입니다. 가 변경되었을 i이 5.6 인스톨, 5 로 인쇄됩니다.

volatile키워드는 이러한 최적화 및 캐싱을 방지하므로 변수를 다른 스레드에 의해 변경할 수 있을 때 유용합니다.

C#과 Java에서 "volatile"은 변수의 값이 프로그램 자체의 범위 밖에서 변경될 수 있으므로 절대 캐시해서는 안 된다는 것을 컴파일러에 알려줍니다.그러면 컴파일러는 변수가 "제어 범위 밖"으로 변경되면 문제를 일으킬 수 있는 최적화를 회피합니다.

휘발성 필드의 읽기에는 의미론이 있습니다.즉, 다음 메모리를 읽기 전에 휘발성 변수에서 메모리를 읽을 수 있습니다.컴파일러가 순서를 변경하는 것을 차단합니다.하드웨어가 그것을 필요로 하는 경우(약하게 순서가 매겨진 CPU)는 특별한 명령을 사용하여 휘발성 읽기 후에 발생하지만 추측적으로 일찍 시작된 읽기를 하드웨어에서 플러시하도록 합니다.그렇지 않으면 CPU는 처음부터 특정 명령어를 방지함으로써 읽기가 조기에 발행되지 않도록 할 수 있습니다.부하의 취득과 폐기 사이에 발생하는 부하의 발생을 방지합니다.

휘발성 필드의 기입에는 릴리스 의미가 있습니다.즉, 휘발성 변수에 대한 메모리 쓰기는 이전의 모든 메모리 쓰기가 다른 프로세서에 표시될 때까지 지연되는 것이 보증됩니다.

다음 예를 생각해 보겠습니다.

something.foo = new Thing();

iffoo이며, 는 "CPU"가 할 수.something 하면 '가치가 나올 수도 foo메모리에 기입하기 에 변경하다Thing이치노이것이 "약순 메모리"의 의미입니다. 있는 할 수 .foo.foovolatile 후 저장하다foo시멘틱스가 는 "Release Semantics"가 "Release Semantics"로 됩니다.foo는 다른 볼수.다른 프로세서에 하기 전에 됩니다.foo생합니니다다

쓰기가 어떻게 가능합니까?foo렇게게 순서? 바? ???이 「」를 보관 유지하고 있는 .foo캐시에 있고 컨스트럭터의 저장소가 캐시를 놓쳤기 때문에 저장소가 캐시에 대한 쓰기를 놓치는 것보다 훨씬 빨리 완료될 수 있습니다.

인텔의 Itanium 아키텍처(아키텍처)는 메모리 순서가 약했습니다.원래의 XBox 360에 사용된 프로세서는 메모리가 약하게 정렬되어 있었습니다.매우 인기 있는 ARMv7-A를 포함한 많은 ARM 프로세서는 메모리가 약하게 정렬되어 있습니다.

개발자들은 종종 이러한 데이터 레이스를 보지 못합니다. 왜냐하면 잠금과 같은 것은 완전한 메모리 장벽이 되기 때문입니다. 기본적으로 시멘틱스를 동시에 획득하고 출시하는 것과 같습니다.잠금을 획득하기 전에는 잠금 내부의 부하를 추측적으로 실행할 수 없으며, 잠금이 획득될 때까지 지연됩니다.잠금을 해제해도 스토어를 지연시킬 수 없습니다.잠금 해제 명령은 잠금 내에서 수행된 모든 쓰기가 글로벌하게 표시될 때까지 지연됩니다.

보다 완전한 예는 "Double-checked locking" 패턴입니다.이 패턴의 목적은 오브젝트를 느리게 초기화하기 위해 항상 잠금을 취득할 필요가 없도록 하는 것입니다.

Wikipedia에서 검색:

public class MySingleton {
    private static object myLock = new object();
    private static volatile MySingleton mySingleton = null;

    private MySingleton() {
    }

    public static MySingleton GetInstance() {
        if (mySingleton == null) { // 1st check
            lock (myLock) {
                if (mySingleton == null) { // 2nd (double) check
                    mySingleton = new MySingleton();
                    // Write-release semantics are implicitly handled by marking
                    // mySingleton with 'volatile', which inserts the necessary memory
                    // barriers between the constructor call and the write to mySingleton.
                    // The barriers created by the lock are not sufficient because
                    // the object is made visible before the lock is released.
                }
            }
        }
        // The barriers created by the lock are not sufficient because not all threads
        // will acquire the lock. A fence for read-acquire semantics is needed between
        // the test of mySingleton (above) and the use of its contents. This fence
        // is automatically inserted because mySingleton is marked as 'volatile'.
        return mySingleton;
    }
}

예에서는, 가 「」에 .MySingleton에 다른 되지 않을 수 .mySingleton이 경우 mySingleton을 엿보는 다른 스레드는 잠금을 획득하지 않으며 반드시 컨스트럭터에 대한 쓰기를 픽업하지 않습니다.

volatile캐시를 방해하지 않습니다.이 기능은, 다른 프로세서가 「표시」하는 기입 순서를 보증합니다.스토어 릴리스는 보류 중인 쓰기가 모두 완료되고 다른 프로세서가 관련 라인을 캐시했을 경우 캐시 라인을 폐기/라이트백하도록 지시하는 버스 사이클이 발행될 때까지 스토어를 지연시킵니다.로드 취득은 추측된 모든 읽기를 플러시하여 이전 값에서 오래된 값이 되지 않도록 합니다.

휘발성이 변수에 미치는 영향을 이해하려면 변수가 휘발성이 아닐 때 어떤 일이 일어나는지 이해하는 것이 중요합니다.

  • 변수는 비휘발성입니다.

2개의 스레드A 및 B가 비휘발성 변수에 액세스 하고 있는 경우 각 스레드는 변수의 로컬복사를 로컬캐시에 유지합니다.로컬 캐시에서 스레드 A에 의해 수행된 변경은 스레드 B에 표시되지 않습니다.

  • 변수는 휘발성입니다.

변수가 휘발성이라고 선언되면 기본적으로 스레드는 이러한 변수를 캐시하지 않아야 합니다.즉, 스레드는 이러한 변수의 값을 메인 메모리에서 직접 읽지 않는 한 신뢰하지 않아야 합니다.

그럼, 언제 변수를 휘발성 변수로 만들까요?

여러 스레드에서 액세스할 수 있는 변수가 있고 모든 스레드가 해당 변수의 최신 업데이트 값을 얻으려면 다른 스레드/프로세스/프로그램 외부에서 값이 업데이트되더라도 이 값을 가져옵니다.

volatile 키워드는 Java와 C# 모두에서 다른 의미를 가집니다.

자바

Java Language Spec:

필드는 휘발성이 있다고 선언될 수 있습니다.이 경우 Java 메모리 모델은 모든 스레드가 변수의 일관된 값을 볼 수 있도록 합니다.

C#

C# 레퍼런스(2021-03-31)에서 다음 내용을 참조해 주세요.

volatile 키워드는 필드가 동시에 실행되는 여러 스레드에 의해 변경될 수 있음을 나타냅니다.컴파일러, 런타임 시스템 및 하드웨어는 성능상의 이유로 메모리 위치에 읽기 및 쓰기를 재배치할 수 있습니다.휘발성이 있다고 선언된 필드는 이러한 최적화의 대상이 되지 않습니다(...).

Java에서는 변수가 동시에 여러 스레드에 의해 사용될 수 있으므로 특정 공통 최적화를 적용할 수 없음을 JVM에 알리기 위해 "volatile"을 사용합니다.

특히 동일한 변수에 액세스하는 두 개의 스레드가 동일한 시스템의 개별 CPU에서 실행되고 있는 상황이 두드러집니다.메모리 액세스 속도가 캐시 액세스 속도보다 훨씬 느리기 때문에 CPU가 보유하고 있는 데이터를 적극적으로 캐시하는 것은 매우 일반적입니다.즉, CPU1에서 데이터가 갱신되면 캐시가 자신을 클리어하기로 결정했을 때가 아니라 즉시 모든 캐시를 통과하여 메인메모리로 이행해야 합니다.이를 통해 CPU2는 갱신된 값을 확인할 수 있습니다(이 경우에도 도중에 모든 캐시를 무시합니다).

비휘발성 데이터를 읽을 때 실행 스레드가 항상 업데이트된 값을 얻거나 얻지 못할 수 있습니다.그러나 객체가 휘발성일 경우 스레드는 항상 최신 값을 가져옵니다.

휘발성이 동시성 문제를 해결하고 있습니다.그 값을 일치시키는 것.이 키워드는 대부분 스레드에서 사용됩니다.여러 스레드가 동일한 변수를 업데이트하는 경우.

언급URL : https://stackoverflow.com/questions/3430757/what-is-the-volatile-keyword-used-for

반응형