programing

Interlocked의 과부하가 없는 이유는 무엇입니까?Double을 매개 변수로 허용하는 추가?

powerit 2023. 5. 8. 22:28
반응형

Interlocked의 과부하가 없는 이유는 무엇입니까?Double을 매개 변수로 허용하는 추가?

스레딩의 원자성을 충분히 높이 평가합니다.인터락된 클래스는 제공합니다. 하지만 왜 추가 기능이 정수용과 롱용의 두 가지 오버로드만 제공하는지 이해할 수 없습니다.그 문제에 대해 Double 또는 다른 숫자 유형이 아닌 이유는 무엇입니까?

분명히, 이중을 변경하기 위한 의도된 방법은 비교입니다.교환; 이중을 수정하는 것이 정수를 수정하는 것보다 더 복잡한 작업이기 때문인 것 같습니다.아직도 왜 그런지는 확실하지 않습니다, 만약 비교한다면.교환 및 추가는 둘 다 정수를 사용할 수 있고, 두 개 모두 이중을 사용할 수 없습니다.

다른 사람들은 "왜?"를 언급했습니다. 직접 것은 .Add(ref double, double) 사용CompareExchange원시:

public static double Add(ref double location1, double value)
{
    double newCurrentValue = location1; // non-volatile read, so may be stale
    while (true)
    {
        double currentValue = newCurrentValue;
        double newValue = currentValue + value;
        newCurrentValue = Interlocked.CompareExchange(ref location1, newValue, currentValue);
        if (newCurrentValue.Equals(currentValue)) // see "Update" below
            return newValue;
    }
}

CompareExchange을 설합니다의 합니다.location1되려고newValue이 현재 값같 은경 우이경과 같으면currentValue원자적이고 스레드 안전한 방식으로 그렇게 하기 때문에 우리는 잠금 장치에 의존하지 않고 단독으로 의존할 수 있습니다.

왜 하필이면while (true)루프? 낙관적으로 동시 알고리즘을 구현할 때는 이와 같은 루프가 표준입니다. CompareExchange되지 않음 변되지않location1이 현재값 와다경과 다른 currentValue을 했습니다.currentValuelocation1 읽기것일 수 않음)를입니다.CompareExchange값을 확인합니다.현재 값(여전히)이 우리가 읽은 값일 경우location1,CompareExchange이 값이 다으변경니다됩로음다로 됩니다.newValue그렇지 않으면 다시 시도해야 합니다.CompareExchange값을 하여 반된 전류값로에서 CompareExchange.

번 다 스 값 까 지 다 스 의 에 변 해 경 된 경 우 드 레 음 른 레 드 이 ▁until 우 ▁the ▁thread 경 된 ▁if ▁by ▁is 경 변 ▁next ▁value ▁the ▁changed ▁another ▁of 다 음 ▁timeCompareExchange다시, 그것은 다시 실패할 것이고, 또 다른 재시도가 필요합니다 - 그리고 이것은 이론적으로 영원히 계속될 수 있습니다, 따라서 루프.여러 스레드에서 값을 지속적으로 변경하지 않는 한,CompareExchange현재 값이 여전히 의 비휘발성 판독치인 경우 한 번만 호출될 가능성이 높습니다.location1만약 그것이 달랐다면, 두 번 양보했습니다.


2022/8/17 업데이트

Strangelove 박사와 Theodor Zoulias가 댓글에서 지적했듯이, 언제.location1 == Double.NaN무한Add() 루프로 변할있습니다.

그래서 옷을 갈아입어야 했습니다.

if (newCurrentValue == currentValue)

로.

if (newCurrentValue.Equals(currentValue))

Interlocked 클래스는 Windows API Interlocked** 함수를 감싼다.

이것들은 차례로 x86에 대한 LOCK 명령어 접두사를 사용하여 네이티브 프로세서 API를 감싸고 있습니다.다음 지시사항 접두사만 지원합니다.

BT, BTS, BTR, BTC, XCHG, XADD, ADD, OR, ADC, SBB, AND, SUB, XOR, NOT, NEG, INC, DEC

여러분은 이것들이 결국 연동된 방법들과 거의 일치한다는 것을 알게 될 것입니다.유감스럽게도 정수가 아닌 유형의 ADD 기능은 여기에서 지원되지 않습니다.64비트 플랫폼에서 64비트 길이에 대한 추가가 지원됩니다.

다음은 명령 수준에서 잠금 의미론을 논의하는 훌륭한 기사입니다.

Reed Copsey가 말했듯이 인터락된 운영 맵은 (Windows API 기능을 통해) x86/x64 프로세서에서 직접 지원하는 명령어에 매핑됩니다.이러한 기능 중 하나가 XCHG라는 것을 고려할 때, 목표 위치의 비트가 무엇을 나타내는지 신경 쓰지 않고 원자 XCHG 연산을 수행할 수 있습니다.즉, 코드는 교환하는 64비트 부동소수점 번호가 실제로 64비트 정수인 것처럼 " 가장"할 수 있으며, XCHG 명령어는 그 차이를 알지 못합니다.따라서.Net은 Interlocked를 제공할 수 있습니다.플로트에 대한 교환 함수와 각각 정수와 긴 정수인 것처럼 "시늉"하여 두 배로 증가합니다.

그러나 다른 모든 작업은 실제로 대상의 개별 비트에서 작동하므로 값이 실제로 정수(또는 경우에 따라 비트 배열)를 나타내지 않는 한 작동하지 않습니다.

저는 두 가지 이유가 있다고 생각합니다.

  1. 대상이 되는 프로세서.정수 유형에 대해서만 NET 지원 연동 증분.저는 이것이 x86의 LOCK 접두사라고 생각합니다. 아마도 다른 프로세서에도 비슷한 지침이 있을 것입니다.
  2. 부동 소수점 번호에 하나를 추가하면 충분히 큰 경우 동일한 숫자가 발생할 수 있으므로 이를 증분이라고 할 수 있을지 모르겠습니다.아마도 프레임워크 설계자들은 이 경우 직관적이지 않은 행동을 피하려고 할 것입니다.

언급URL : https://stackoverflow.com/questions/1400465/why-is-there-no-overload-of-interlocked-add-that-accepts-doubles-as-parameters

반응형