-
21-09-2019 - |
문제
당신은 무엇을 의미하는 원자 지?
은 어떻게 다음이 될 원자?
TestAndSet
int TestAndSet(int *x){
register int temp = *x;
*x = 1;
return temp;
}
에서 소프트웨어의 관점 하면,사용하지 않으려고 비 차단하는 동기화 기본 형식할 수 있는 방법 하나인 자성의 지?은 그것을 가능하에서만 하드웨어 또는 몇 가지 어셈블리 레벨 지시어 최적화를 사용할 수 있습니까?
해결책
일부 기계 지침은 본질적으로 원자입니다. 예를 들어, 기본 프로세서의 적절한 정렬 된 값을 읽고 쓰는 것은 원자입니다. 많은 아키텍처에서.
이는 하드웨어 인터럽트, 다른 프로세서 및 하이퍼 스레드가 읽기 또는 저장을 방해하고 동일한 위치에 부분 값을 읽거나 쓸 수 없음을 의미합니다.
원자 적으로 함께 읽고 쓰는 것과 같은 더 복잡한 것들은 명백한 원자 기계 지침 (예 : x86의 cmpxchg)에 의해 달성 될 수 있습니다.
잠금 및 기타 고급 구조는 이러한 원자 원시를 기반으로하며, 일반적으로 단일 프로세서 단어 만 보호합니다.
단일 독자와 작가 사이에 공유 된 링크 된 목록에서 또는 여러 독자 및 작가 간의 링크 된 목록에서 Pointers의 읽기 및 쓰기만으로도 일부 영리한 동시 알고리즘을 구축 할 수 있습니다.
다른 팁
원자에서 온 그리스 ἄτομος(atomos)의미하는"분". (주의:난 말하지 않는 그리스어,그래서 어쩌면 그것은 정말 뭔가 다른 것이지만,대부분의 영어 스피커 인용하는 어원은 그것을 해석하는 이 방법입니다.:-)
컴퓨팅에서,즉,작동,아, 일.이 없는 중간 상태 표시하기 전에 완료됩니다.그래서 만약 당신의 CPU 가 중단되면 서비스 하드웨어(IRQ),또는 다른 CPU 을 읽고 동일한 메모리에 영향을 미치지 못한 결과,그리고 이러한 다른 작업을 관찰하는 그것으로 완료되거나 시작하지 않습니다.
로 예...말 당신이 원하는 변수를 설정하는 무언가를하지만,경우에만 설정되지 않았다.당신이 있는 경향이 이렇게하려면:
if (foo == 0)
{
foo = some_function();
}
하지만 만일 이 병렬로 실행?그것은 될 수 있는 프로그램를 가져옵니다 foo
, 볼,제로,그 사이에 스레드 2 고 같은 값을 설정합니다.다시 원본 스레드에서,코드는 여전히 생각하 foo
로,그리고 변수정이다.
에 대한 이 같은 경우,CPU 제공하는 일부의 지침을 할 수있는 비교와 조건으로 할당하는 원자 entity.따라서,테스트 및 세트,compare-and-swap 및 부하가 연결되어/저장 조건입니다.당신이 사용할 수 있습을 구현하는 자물쇠(하는 C 라이브러리는 이 프로젝트를 진행했습니다.) 거나 작성할 수 있습 one-off 알고리즘에 의존하는 기본 형식이 뭔가를 할 수 있습니다.(거기에 멋진 물건을 할 여기에,하지만 대부분의 단순한 인간 이해의 두려움을 받고 그것이 잘못입니다.)
원자력은 공유 리소스를 포함하는 모든 형태의 병렬 처리 (데이터 협력 또는 공유 데이터 포함)가있을 때 핵심 개념입니다.
문제는 예로 잘 설명되어 있습니다. 파일을 만들려고하지만 파일이 아직 존재하지 않는 경우에만 파일을 만들려는 두 가지 프로그램이 있다고 가정 해 봅시다. 두 프로그램 중 하나는 언제든지 파일을 만들 수 있습니다.
당신이 그렇게한다면 (당신의 예에있는 것이기 때문에 c를 사용하겠습니다) :
...
f = fopen ("SYNCFILE","r");
if (f == NULL) {
f = fopen ("SYNCFILE","w");
}
...
다른 프로그램이 Open for Read와 Open for Write 사이에 파일을 만들지 않았 음을 확신 할 수 없습니다.
직접 할 수있는 방법이 없으며 운영 체제의 도움이 필요합니다. 일반적 으로이 목적을위한 Syncronization Primitives 또는 원자력으로 보장되는 다른 메커니즘 (예 : 잠금 작동이 원자가 인 관계형 데이터베이스입니다. 또는 프로세서 "테스트 및 설정"명령어와 같은 하위 레벨 메커니즘).
중 일부는 아래의 메모에 자성을 이해할 수 있게 도와주는 의미를 파악합니다.노트 소스에서 나와서 내가 읽는 것이 좋습니다 그들 중 일부는 필요하신 경우 자세한 설명보다는 점이 형식으로 글머리 기호입니다.세 어떠한 오류도록 수정할 것입니다.
정의:
- 그리스에서 의미하는"수없는 작은 부분으로"
- 는"원자"작업은 항상 관측 수행하 또는 수행하지 않지만, 적 halfway done.
- 원자 작업이 수행되어야 함 또는 전적으로 수행되지 않습 니다.
- 멀티 스레드 시나리오는 변수가에서 unmutated 하기 돌연변이 직접 없이"중 돌연변이"값
예제 1:Atomic Operations
다음 사항을 고려 정수를 사용하여 다른 스레드:
int X = 2; int Y = 1; int Z = 0; Z = X; //Thread 1 X = Y; //Thread 2
위의 예에서,두 개의 스레드를 이용하의 X,Y,Z
- 각각 읽고 쓰기가 atomic
- 스레드 경주 할 것이다:
- 면 쓰레드는 1wins,다음 Z=2
- 만약 thread2wins,다음 Z=1
- Z 것입니다 확실히 하나의 이 두 값이
예제 2:Non-Atomic Operations:++/--Operations
고려의 증가/감소 식:
i++; //increment i--; //decrement
Operations 번역:
- 읽기 i
- 증가/감소 읽은 값
- 쓰 새로운 값을 다시 나
- 작업이 각각의 구성 3atomic operations,고 있지 않은 원자 자신
- 두 개의 시도를 증가시키는 나는 별도의 스레드에서 수 백지를 끼워 넣는 것과 같은 하나의 단위로 잃
예시 3-Non-Atomic Operations:큰 값보다 4-Bytes
- 을 고려한 다음 변경할 수 없는 구조체:
struct MyLong { public readonly int low; public readonly int high; public MyLong(int low, int high) { this.low = low; this.high = high; } }
우리가 만드는 분야는 특정 유형의 값 MyLong:
MyLong X = new MyLong(0xAAAA, 0xAAAA); MyLong Y = new MyLong(0xBBBB, 0xBBBB); MyLong Z = new MyLong(0xCCCC, 0xCCCC);
우리는 수정의 필드에는 별도의 스레드 실 없이 안전
X = Y; //Thread 1 Y = X; //Thread 2
습니다.NET,복사하는 경우 값을 입력,CLR 지 않는 전화 생성자-이동 바이트 중 하나는 원자로 동시에 이용하실 수 있습니다
- 이 때문에,운영에서 두 개의 스레드가 지금은 네 atomic operations
- 없는 경우에는 스레드에 안전 적용할 수 있는 데이터 손상
다음 사항을 고려의 실행 순서 작업:
X.low = Y.low; //Thread 1 - X = 0xAAAABBBB Y.low = Z.low; //Thread 2 - Y = 0xCCCCBBBB Y.high = Z.high; //Thread 2 - Y = 0xCCCCCCCC X.high = Y.high; //Thread 1 - X = 0xCCCCBBBB <-- corrupt value for X
읽기와 쓰기 보다 큰 값은 32 비트에서 여러 스레드에서 32 비트 운영체제를 추가하지 않고 어떤 종류의 잠금을 조작하기 위해 원자이 발생 가능성이 높 손상 위와 같이 데이터
프로세서 Operations
에 모든 현대적인 프로세서,가정할 수 있습 읽고 쓰는 자연스럽게 정렬되는 기본 유형은 원자로:
- 1:메모리 버스가 최소한 유형으로 읽거나 쓰
- 2:CPU 읽기 및 쓰기를 이러한 유형에서 하나의 버스,트랜잭션을 만드는 것이 불가능한 다른 스레드에서 그들을 보고 반 완료된 상태
On x86 및 X64 보장은 없는 읽기 및 쓰기보다 더 큰 여덟 바이트를 원
- 프로세서 공급업체의 원자 작업에 대한 각 프로세서 소프트웨어 개발자의 설명서
- 에 단일 프로세서의/단 하나 중핵 시스템에서 사용 가능한 표준에 잠금을 방지하는 기술 CPU 에서 지침이 중단되지만,이 비효율적일 수 있습
- 인터럽트를 비활성화 또 다른 더욱 효율적인 솔루션을 가능한 경우
- 에서 다중 프로세서/멀티 코어 시스템을 잠금을 사용하지만 단지 하나를 사용하여 명령하거나 비활성화를 중단을 보증하지 않 원자 액세스
- 원자성에 의해 달성될 수 있습을 보장하는 지침을 사용 assert'잠'신호는 버스에서 다른 프로세서 시스템에 액세스하는 메모리를 동시에
언어 차이
C#
- C#보장하는 작업에 어떤 내장 값의 형식을 취하는 4 바이트를 원
- 작업에 가치 유형을 개 이상의 바이트(double,long,etc.) 을 보장하지는 않습 atomic
- CLI 보장 읽고 쓰는 변수 값의 형식은 크기(또는 작게)프로세서의 자연적인 포인터 크기의 원자
- Ex-실행 C#64 비트 OS 에서 64 비트 버전의 CLR 수행 읽기와 쓰기의 64 비트 두 배 긴 정수를 자동으로
- 을 만드는 원자 작업:
- .NET provodes Interlocked 클래스의 일부분으로 시스템입니다.실을 꿰는 네임스페이스
- Interlocked 클래스를 제공합 원자 작업과 같은 증가 비교,exchange,etc.
using System.Threading; int unsafeCount; int safeCount; unsafeCount++; Interlocked.Increment(ref safeCount);
C++
- C++표준을 보증하지 않 원자 행동
- 모든 C/C++작업으로 추정된 비-원자 지정되지 않는 한 컴파일러에 의해 또는 하드웨어 공급 업체-포함하여 32-bit integer 할당
- 을 만드는 원자 작업:
- C++11concurrency 라이브러리 포함-Atomic Operations 라이브러리()
- 원자 라이브러리를 제공합 원자로 형식 템플릿 클래스를 사용하와 함께 당신이 원하는 모든 유형
- 작업에 원자 종류는 원자고 이렇게 스레드를 안전
구 AtomicCounter
{std::atomic< int> value; void increment(){ ++value; } void decrement(){ --value; } int get(){ return value.load(); }
}
Java
- Java 보장하는 작업에 어떤 내장 값의 형식을 취하는 4 바이트를 원
- 당하 휘발성 갈망과 복식은 또한 보장을 원
- Java 제공하는 소 툴킷을 지원하는 클래스 잠금 스레드에 안전 프로그래밍에 하나의 변수를 통해 java.util.동시에 이루어 집니다.atomic
- 이 제공하는 원자 잠금 작업을 기반으로 낮은 수준의 원자 하드웨어 기본 형식과 같은 compare-and-swap(CAS)이라고도 불리는 비교하고 설정:
- CAS 식-boolean compareAndSet(expectedValue,updateValue);
- 이 방법은 자동으로 변수를 설정 updateValue 는 경우 그것은 현재 보유하고 expectedValue-보고 진정한 성공에
- CAS 식-boolean compareAndSet(expectedValue,updateValue);
import java.util.concurrent.atomic.AtomicInteger; public class Counter { private AtomicInteger value= new AtomicInteger(); public int increment(){ return value.incrementAndGet(); } public int getValue(){ return value.get(); } }
원자력은 OS에 의해서만 보장 될 수 있습니다. OS는 기본 프로세서 기능을 사용하여이를 달성합니다.
따라서 자신의 TestandSet 기능을 만드는 것은 불가능합니다. (인라인 ASM 스 니펫을 사용할 수 있는지 확실하지 않지만 TestAndSet Mnemonic을 직접 사용할 수 있습니다 (이 진술은 OS 특권으로 만 수행 할 수 있습니다).
편집 :이 게시물 아래의 주석에 따르면 ASM 지시문을 직접 사용하여 자신만의 'BittestandSet'기능을 만들 수 있습니다 (Intel x86에서). 그러나 이러한 트릭이 다른 프로세서에서도 작동하는 경우 명확하지 않습니다.
나는 내 요점을지지한다 : 당신이 attoic 일을하고 싶다면, OS 기능을 사용하고 직접하지 마십시오.