답변:
마지막 두 개는 동일합니다. "원자"는 기본 동작입니다 ( 실제로는 키워드가 아니며nonatomic
atomic
, llvm / clang의 최신 버전에서는 키워드로 - 가 추가 되지 않은 경우에만 지정됨).
메소드 구현을 @synthesizing한다고 가정하면 원자 대 비 원자는 생성 된 코드를 변경합니다. 자신의 세터 / 게터를 작성하는 경우 원자 / 비 원자 / 유지 / 할당 / 복사는 단지 자문 일뿐입니다. (참고 : @synthesize는 이제 LLVM의 최신 버전에서 기본 동작입니다. 인스턴스 변수를 선언 할 필요도 없습니다. 인스턴스 변수도 자동으로 합성되며 _
우발적 인 직접 액세스를 방지하기 위해 이름 앞에 추가됩니다.)
"원자"를 사용하면 합성 된 setter / getter는 다른 스레드의 setter 활동에 관계없이 getter에서 전체 값이 반환되거나 setter가 설정하도록합니다. 즉, 스레드 A가 게터의 중간에 있고 스레드 B가 세터를 호출하면 실제 실행 가능한 값 (자동 해제 된 개체)이 A의 호출자에게 반환됩니다.
에서 nonatomic
그러한 보증은 이루어지지 않습니다. 따라서 nonatomic
"원자"보다 상당히 빠릅니다.
"원자"가하지 않는 것은 스레드 안전을 보장하는 것입니다. 스레드 A가 스레드 B와 동시에 getter를 호출하고 C가 다른 값을 가진 setter를 호출하는 경우 스레드 A는 반환 된 세 값 중 하나 또는 설정자에 전달 된 값 중 하나를 리턴 할 수 있습니다. 마찬가지로, 객체는 알 수없는 방식으로 B 또는 C의 값으로 끝날 수 있습니다.
멀티 스레드 프로그래밍의 주요 과제 중 하나 인 데이터 무결성 보장은 다른 방법으로 달성됩니다.
이것에 추가 :
atomicity
단일 속성 중 하나는 여러 종속 속성이 재생 중일 때 스레드 안전성을 보장 할 수 없습니다.
치다:
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;
이 경우 스레드 A는을 호출 setFirstName:
한 다음 호출 하여 객체의 이름을 바꿀 수 있습니다 setLastName:
. 그 동안 스레드 B는 fullName
스레드 A의 두 호출 사이에서 호출 할 수 있으며 이전 성과 결합 된 새로운 이름을받습니다.
이를 해결하려면 트랜잭션 모델 이 필요합니다 . 즉 fullName
, 종속 속성이 업데이트되는 동안 액세스를 제외 할 수있는 다른 종류의 동기화 및 / 또는 제외 .
@property NSArray* astronomicalEvents;
입니다. UI에 표시하려는 데이터가 나열된 예가 있습니다. 애플리케이션이 시작되면 포인터가 빈 배열을 가리키면 앱이 웹에서 데이터를 가져옵니다. 웹 요청이 (다른 스레드에서) 완료되면 앱이 새 배열을 작성하고 속성을 원자 적으로 새 포인터 값으로 설정합니다. 스레드 안전하고 빠진 것이 아니라면 잠금 코드를 작성할 필요가 없습니다. 나에게 꽤 유용한 것 같습니다.
atomic
교차 스레드 반값 읽기를 방지합니다. (추적하기에 재미있는 버그였습니다.)
retain/autorelease
춤을 추지 않고 객체를 반환합니다 . 스레드 B가 객체를 해제합니다. 스레드 A가 붐을 일으 킵니다 . atomic
스레드 A가 리턴 값에 대한 강력한 참조 (+1 보유 횟수)를 갖도록합니다.
이것은 Apple의 문서에 설명되어 있지만 아래는 실제로 일어나는 일의 예입니다.
"atomic"키워드가 없으며 "nonatomic"을 지정하지 않으면 속성이 원자 적이지만 "atomic"을 명시 적으로 지정하면 오류가 발생합니다.
"비 원자"를 지정하지 않으면 속성이 원자 적이지만 원하는 경우 최신 버전에서 "원자"를 명시 적으로 지정할 수 있습니다.
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
이제 원자 변형은 조금 더 복잡합니다.
//@property(retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}
- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName_ retain];
[userName release];
userName = userName_;
}
}
기본적으로 원자 버전은 스레드 안전성을 보장하기 위해 잠금을 수행해야하며 호출자에게 객체가 존재하도록 객체의 참조 횟수와 객체의 균형을 잡기 위해 자동 해제 횟수를 충돌시킵니다. 다른 스레드가 값을 설정하여 참조 횟수가 0으로 떨어지면 잠재적 경쟁 조건입니다.
실제로 속성이 스칼라 값인지 개체인지, 유지, 복사, 읽기 전용, 비 원자 등이 상호 작용하는 방식에 따라 이러한 방식이 작동하는 방식에는 여러 가지 변형이 있습니다. 일반적으로 속성 신디사이저는 모든 조합에 대해 "올바른 일"을 수행하는 방법 만 알고 있습니다.
@property (assign) id delegate;
아무것도 동기화되지 않습니다 (iOS SDK GCC 4.2 ARM -Os
) . [self.delegate delegateMethod:self];
와 사이에 경쟁이 있음을 의미 foo.delegate = nil; self.foo = nil; [super dealloc];
합니다. stackoverflow.com/questions/917884/…
_val
/ val
가 무엇인지 확실 하지 않지만 실제로는 아닙니다. 원자 copy
/ retain
속성에 대한 getter 는 다른 스레드에서 setter가 호출되어 참조 횟수가 0이되는 객체를 반환하지 않도록해야합니다. 본질적으로 ivar를 읽고 유지하면서 setter 가하지 않도록해야합니다. 덮어 쓰고 해제 한 다음 자동 해제하여 보존 상태를 조정합니다. 그것은 본질적으로 getter와 setter가 잠금을 사용해야 함을 의미 합니다 (메모리 레이아웃이 수정 된 경우 CAS2 명령으로 가능해야합니다. 아아 -retain
는 메서드 호출입니다).
차이점을 이해하는 가장 좋은 방법은 다음 예제를 사용하는 것입니다.
"name"이라는 원자 문자열 특성이 있다고 가정 [self setName:@"A"]
하고 스레드 A에서 호출 [self setName:@"B"]
하고 스레드 B에서 호출 [self name]
하고 스레드 C에서 호출 하면 다른 스레드에 대한 모든 조작이 순차적으로 수행되며 이는 하나의 스레드가 setter를 실행 중임을 의미합니다. 또는 getter이면 다른 스레드가 기다립니다.
이렇게하면 속성 "name"이 (가) 읽기 / 쓰기 안전 상태가되지만 다른 스레드 D가 [name release]
동시에 호출 하면 여기에 관련된 setter / getter 호출이 없기 때문에이 작업으로 인해 충돌이 발생할 수 있습니다. 즉, 다른 스레드가 동시에 모든 유형의 메시지를 객체에 보낼 수 있으므로 객체는 읽기 / 쓰기 안전 (ATOMIC)이지만 스레드로부터 안전하지 않습니다. 개발자는 이러한 객체에 대한 스레드 안전성을 보장해야합니다.
"name"속성이 원자가 아닌 경우 위의 예-A, B, C 및 D에있는 모든 스레드가 동시에 실행되어 예기치 않은 결과가 생성됩니다. 원자의 경우 A, B 또는 C 중 하나가 먼저 실행되지만 D는 여전히 병렬로 실행될 수 있습니다.
구문과 의미는 이미이 질문에 대한 다른 훌륭한 답변으로 잘 정의되어 있습니다. 때문에 실행 과 성능을 잘 설명되지 않습니다, 나는 내 대답을 추가합니다.
이 3의 기능적 차이점은 무엇입니까?
나는 항상 원자를 기본적으로 매우 흥미로운 것으로 생각했습니다. 추상화 수준에서 클래스의 원자 속성을 차량으로 사용하여 100 % 스레드 안전성을 달성하는 것이 가장 중요합니다. 진정한 올바른 멀티 스레드 프로그램을 위해서는 프로그래머의 개입이 거의 필요합니다. 한편, 성능 특성 및 실행은 아직 자세히 설명되지 않았습니다. 수년 동안 엄청나게 멀티 스레드 된 프로그램을 작성해온 결과, nonatomic
원자는 어떤 목적으로도 감지 할 수 없었기 때문에 내 속성을 전체적으로 선언했습니다 . 이 질문에 대한 원자 및 비 원자 특성의 세부 사항을 논의하는 동안 일부 프로파일 링에서 흥미로운 결과가 발생했습니다.
실행
확인. 가장 먼저 정리하고 싶은 것은 잠금 구현이 구현 정의되고 추상화된다는 것입니다. Louis는 @synchronized(self)
그의 예에서 사용합니다 . 나는 이것을 일반적인 혼란의 근원으로 보았습니다. 구현은 실제로 사용 하지 않습니다 @synchronized(self)
. 객체 레벨 스핀 잠금을 사용합니다 . Louis의 일러스트레이션은 우리 모두에게 친숙한 구문을 사용하는 고급 일러스트레이션에는 적합하지만 사용하지 않는 것이 중요합니다 @synchronized(self)
.
또 다른 차이점은 원자 속성이 게터 내에서 객체를 유지 / 해제하는 것입니다.
공연
흥미로운 부분은 다음과 같습니다. 경합되지 않은 (예 : 단일 스레드) 경우 에 원자 속성 액세스를 사용하는 성능 은 경우에 따라 매우 빠릅니다. 이상적인 경우보다 적은 경우 원자 액세스를 사용하면 오버 헤드의 20 배 이상이 소요될 수 있습니다 nonatomic
. 7 개의 스레드를 사용 하는 컨테스트 된 케이스는 3 바이트 구조 (2.2GHz 코어 i7 쿼드 코어, x86_64)의 경우 44 배 느 렸습니다 . 3 바이트 구조체는 매우 느린 속성의 예입니다.
흥미로운 참고 사항 : 3 바이트 구조체의 사용자 정의 접근자는 합성 원자 접근 자보다 52 배 빠릅니다. 또는 합성 된 비 원자 접근 자의 속도 84 %
분쟁이 발생한 경우의 개체도 50 배를 초과 할 수 있습니다.
구현의 최적화 및 변형이 많기 때문에 이러한 상황에서 실제 영향을 측정하는 것은 매우 어렵습니다. "프로필을 작성하여 문제가 발견되지 않는 한 신뢰하기"와 같은 소리가 들릴 수 있습니다. 추상화 수준으로 인해 실제로 실제 영향을 측정하는 것은 매우 어렵습니다. 프로파일에서 실제 비용을 모으는 데는 시간이 많이 걸리고 추상화로 인해 매우 정확하지 않을 수 있습니다. 또한 ARC 대 MRC는 큰 차이를 만들 수 있습니다.
따라서 속성 액세스 구현에 중점을 두지 않고 뒤로 물러서 봅시다 . 우리는 일반적인 용의자를 포함시키고 objc_msgSend
, 경합되지 않은 경우 NSString
게터에 대한 많은 호출에 대한 실제 높은 수준의 결과를 조사합니다 (초 단위 값).
짐작할 수 있듯이, 참조 카운트 활동 / 사이클링은 원자와 ARC 하에서 중요한 기여자입니다. 또한 이의 제기 된 사례에서 더 큰 차이를 볼 수 있습니다.
나는 성능에 세심한주의를 기울이지 만, 여전히 Semantics First 라고 말합니다 ! . 한편, 많은 프로젝트에서 성능은 우선 순위가 낮습니다. 그러나 실행 세부 사항과 사용하는 기술 비용을 아는 것이 확실합니다. 필요, 목적 및 능력에 맞는 기술을 사용해야합니다. 이 방법을 사용하면 몇 시간의 비교 시간을 절약하고 프로그램을 디자인 할 때보다 정확한 결정을 내릴 수 있기를 바랍니다.
NSString
하지 않은 단일 스레드 케이스에 대해 10.8을 목표로 동일한 컴퓨터에서 10.8.5로 테스트했습니다 -ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102%
. 결과는 오늘날과 조금 다릅니다. 나는 @synchronized
비교를 하지 않았다 . @synchronized
의미 론적으로 다르며, 사소한 동시 프로그램이 있으면 좋은 도구라고 생각하지 않습니다. 속도가 필요한 경우 피하십시오 @synchronized
.
원자 = 스레드 안전
비 원자 = 나사산 안전 없음
인스턴스 변수는 런타임 환경에 의한 스레드 실행의 스케줄링 또는 인터리빙에 관계없이 호출 스레드에서 추가 동기화 또는 기타 조정없이 여러 스레드에서 액세스 할 때 올바르게 작동하는 경우 스레드 안전합니다.
스레드가 인스턴스 값을 변경하면 변경된 값을 모든 스레드에서 사용할 수 있으며 한 번에 하나의 스레드 만 값을 변경할 수 있습니다.
atomic
:다중 스레드 환경에서 인스턴스 변수에 액세스하는 경우
atomic
:런타임에서 워치 독 작업이 필요하지 않기 nonatomic
때문에 빠르지 nonatomic
않습니다.
nonatomic
:여러 스레드에서 인스턴스 변수를 변경하지 않을 경우 사용할 수 있습니다. 성능이 향상됩니다.
원자 속성과 비 원자 속성에 대한 설명을 여기에서 찾아 냈습니다 . 다음은 동일한 관련 텍스트입니다.
'원자'는 분류 할 수 없음을 의미합니다. OS / 프로그래밍 용어에서 원자 함수 호출은 중단 할 수없는 호출입니다. 전체 함수를 실행해야하며, 완료 될 때까지 OS의 일반적인 컨텍스트 전환으로 CPU에서 스왑하지 않아야합니다. 알지 못하는 경우를 대비하여 : CPU는 한 번에 하나의 작업 만 수행 할 수 있으므로 OS는 작은 시간 단위로 실행중인 모든 프로세스에 대한 CPU 액세스를 환상으로 전환합니다.멀티 태스킹 CPU 스케줄러는 실행 중 언제라도 (중간 함수 호출에서도) 프로세스를 중단시킬 수 있습니다. 따라서 두 프로세스가 동시에 변수를 업데이트하려고 할 수있는 공유 카운터 변수 업데이트와 같은 작업의 경우 '원자 적으로'실행되어야합니다. 즉, 각 프로세스가 다른 프로세스로 교체되기 전에 각 업데이트 작업이 완전히 완료되어야합니다. CPU.
따라서이 경우 원자는 속성 판독기 메소드를 중단 할 수 없다는 것을 의미합니다. 실제로 메소드가 읽은 변수가 다른 스레드 / 호출 / 함수가 가져 오기 때문에 절반의 값을 변경할 수 없음을 의미합니다. CPU로 교체되었습니다.
atomic
변수를 인터럽트 할 수 없으므로 어느 시점에서든 변수에 포함 된 값은 (스레드 잠금) 손상되지 않도록 보장되지만이 스레드 잠금을 보장 하면 변수에 대한 액세스 속도가 느려집니다. non-atomic
반면에 변수는 그러한 보장을하지 않지만 더 빠른 액세스를 제공합니다. 요약하면 non-atomic
여러 스레드가 동시에 변수에 액세스하지 않고 속도를 높일 수 있다는 것을 알고있을 때 계속 하십시오.
너무 많은 기사를 읽고 Stack Overflow 게시물을 작성하고 데모 응용 프로그램에서 가변 속성 속성을 확인한 후 모든 속성 정보를 하나로 묶기로 결정했습니다.
atomic
// 기본nonatomic
strong = retain
// 기본weak = unsafe_unretained
retain
assign
// 기본unsafe_unretained
copy
readonly
readwrite
// 기본iOS의 변수 속성 속성 또는 수정 자 기사 에서 위에서 언급 한 모든 속성을 찾을 수 있으며 이는 확실히 도움이 될 것입니다.
atomic
atomic
하나의 스레드 만 변수에 액세스 함을 의미합니다 (정적 유형).atomic
스레드 안전합니다.atomic
기본 동작입니다예:
@property (retain) NSString *name;
@synthesize name;
nonatomic
nonatomic
변수에 대한 다중 스레드 액세스 (동적 유형)를 의미합니다.nonatomic
스레드 안전하지 않습니다.nonatomic
기본 동작이 아닙니다. nonatomic
속성 속성에 키워드 를 추가해야 합니다.예:
@property (nonatomic, retain) NSString *name;
@synthesize name;
원자는 속성에 대한 액세스가 원자 방식으로 수행되도록 보장합니다. 예를 들어 항상 완전히 초기화 된 객체를 반환합니다. 한 스레드의 속성 가져 오기 / 설정은 다른 스레드가 액세스하기 전에 완료해야합니다.
두 개의 스레드에서 한 번에 다음 기능이 발생한다고 생각하면 결과가 좋지 않은 이유를 알 수 있습니다.
-(void) setName:(NSString*)string
{
if (name)
{
[name release];
// what happens if the second thread jumps in now !?
// name may be deleted, but our 'name' variable is still set!
name = nil;
}
...
}
장점 : 매번 완전히 초기화 된 객체를 반환하면 멀티 스레딩의 경우 최상의 선택입니다.
단점 : 성능 저하, 실행 속도가 약간 느려짐
원자와 달리 매번 완전히 초기화 된 객체 반환을 보장하지는 않습니다.
장점 : 매우 빠른 실행.
단점 : 멀티 스레딩의 경우 가비지 값이 발생할 가능성이 있습니다.
가장 쉬운 답변 : 두 번째 예제 사이에는 차이가 없습니다. 기본적으로 속성 접근자는 원자 적입니다.
가비지 수집되지 않은 환경 (예 : 유지 / 릴리스 / 자동 릴리스 사용)의 원자 접근자는 다른 스레드가 값의 올바른 설정 / 가져 오기를 방해하지 않도록 잠금을 사용합니다.
멀티 스레드 응용 프로그램을 만들 때의 추가 정보 및 기타 고려 사항에 대해서는 Apple Objective-C 2.0 설명서 의 " 성능 및 스레딩 "섹션을 참조하십시오.
원자는 스레드 안전 , 그것은 천천히 그리고 잘 보증한다 (보장 할 수 없습니다) 많은 스레드가 동일한 영역에 대한 액세스를 시도하는 방법에만 고정 값에 상관없이 제공되지 않습니다. 아토믹 (atomic)을 사용할 때,이 함수 안에 작성된 코드 조각은 한 번에 하나의 스레드 만 실행할 수있는 중요 섹션의 일부가됩니다.
스레드 안전 만 보장합니다. 보장하지 않습니다. 내 말은 당신이 당신의 차를 위해 전문 운전자를 고용한다는 것입니다. 그럼에도 불구하고 자동차가 사고를 당하지 않을 것이라고 보장하지는 않습니다. 그러나 가능성은 가장 적습니다.
원자-그것은 나눌 수 없으므로 결과가 기대됩니다. 비 원자-다른 스레드가 메모리 영역에 액세스하면이를 수정할 수 있으므로 예상치 못한 결과가 발생합니다.
코드 토크 :
원자는 속성 스레드의 getter 및 setter를 안전하게 만듭니다. 예를 들어 u가 다음과 같이 쓴 경우 :
self.myProperty = value;
스레드 안전합니다.
[myArray addObject:@"Abc"]
스레드 안전하지 않습니다.
"atomic"이라는 키워드가 없습니다
@property(atomic, retain) UITextField *userName;
위와 같이 사용할 수 있습니다
@property(retain) UITextField *userName;
@property (atomic, retain) NSString * myString을 사용하면 문제가 발생하는 스택 오버플로 질문을 참조하십시오 .
원자 (기본값)
원자가 기본값입니다. 아무 것도 입력하지 않으면 속성이 원 자성입니다. 원자 속성은 그 속성을 읽으려고하면 유효한 값을 얻습니다. 그 값이 무엇인지에 대해 보증하지는 않지만 정크 메모리뿐만 아니라 좋은 데이터를 얻을 수 있습니다. 이것이 할 수있는 것은 단일 변수를 가리키는 다중 스레드 또는 다중 프로세스가있는 경우 하나의 스레드가 읽고 다른 스레드가 쓸 수있는 것입니다. 동시에 충돌하면 리더 스레드는 변경 전 또는 변경 후 두 값 중 하나를 얻습니다. 원자가 제공하지 않는 것은 어떤 값을 얻을 수 있는지에 대한 보증입니다. 원자는 실제로 스레드 안전과 혼동되기 때문에 정확하지 않습니다. 다른 방법으로 스레드 안전을 보장해야합니다.
비 원자
반대로, 원자가 아닌 것은 아마도 "원자 적 일을하지 말라"는 것을 의미 할 것입니다. 당신이 잃어버린 것은 항상 무언가를 되 찾는다는 보장입니다. 쓰기 도중에 읽으려고하면 가비지 데이터를 다시 얻을 수 있습니다. 그러나 다른 한편으로는 조금 더 빠릅니다. 원자 속성은 값을 되 찾을 수 있도록 약간의 마법을 수행해야하기 때문에 조금 느립니다. 그것이 당신이 많이 접근하는 재산이라면, 당신은 그 속도 패널티가 발생하지 않도록 비 원자력으로 드롭 다운 할 수 있습니다.
자세한 내용은 여기를 참조하십시오 : https://realm.io/news/tmi-objective-c-property-attributes/
기본 이다 atomic
이 방법은 당신이 속성을 사용할 때마다 당신에게 성능 비용 않지만, 스레드 안전합니다. Objective-C는 잠금을 설정하므로 setter / getter가 실행되는 한 실제 스레드 만 변수에 액세스 할 수 있습니다.
ivar _internal이있는 속성의 MRC를 사용한 예 :
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
마지막 두 개는 동일합니다.
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName; // defaults to atomic
반면에 nonatomic
코드 에는 아무것도 추가하지 않습니다. 따라서 보안 메커니즘을 직접 코딩하는 경우에만 스레드 안전합니다.
@property(nonatomic, retain) UITextField *userName;
키워드를 첫 번째 속성 속성으로 쓰지 않아도됩니다.
잊지 마십시오. 이것이 속성 전체가 스레드로부터 안전하다는 것을 의미하지는 않습니다. setter / getter의 메소드 호출 만 있습니다. 그러나 setter를 사용하고 그 후에 getter를 동시에 2 개의 다른 스레드로 사용하면 깨질 수도 있습니다!
시작하기 전에 : 새 라이터가 발생하려면 메모리의 모든 객체를 메모리에서 할당 해제해야합니다. 종이에 쓰는 것처럼 단순히 위에 글을 쓸 수는 없습니다. 당신은 있어야합니다 첫 번째 (할당 해제)을 삭제를하고 당신은 그것에 쓸 수 있습니다. 지우기가 완료된 (또는 절반이 완료된) 시점에서 아직 쓰지 않은 (또는 절반이 쓴) 아무것도 읽지 않으면 매우 문제가 될 수 있습니다! 원자 및 비 원자 (nonatomic)는이 문제를 다른 방식으로 처리하는 데 도움이됩니다.
먼저 읽기 이 질문을하고 읽을 Bbum의 답변을 . 또한 내 요약을 읽으십시오.
atomic
항상 보증합니다
보유 횟수는 Objective-C에서 메모리가 관리되는 방식입니다. 객체를 만들 때 유지 횟수는 1입니다. 객체에 보관 메시지를 보내면 보관 횟수가 1 씩 증가합니다. 객체를 릴리즈 메시지를 보내면 보관 횟수가 1 씩 감소합니다. 객체에 자동 해제 메시지를 보내면 향후 보유 단계에서 보유 횟수가 1 씩 감소합니다. 오브젝트의 보유 횟수가 0으로 줄어들면 할당이 해제됩니다.
뭐?! 멀티 스레딩과 스레드 안전성이 다른가요?
예. 멀티 스레딩은 여러 스레드가 동시에 공유 된 데이터 조각을 읽을 수 있으며 충돌하지는 않지만 자동 릴리스되지 않은 값에서 읽지 않는다고 보장하지는 않습니다. 스레드 안전을 사용하면 읽은 내용이 자동으로 해제되지 않습니다. 우리가 기본적으로 모든 것을 원자 적으로 만들지 않는 이유는 성능 비용이 있고 대부분의 경우 스레드 안전이 필요하지 않기 때문입니다. 코드의 일부에는 필요하고 그 일부에는 잠금, 뮤텍스 또는 동기화를 사용하여 스레드 안전 방식으로 코드를 작성해야합니다.
nonatomic
전반적으로 두 가지 측면에서 다릅니다.
자동 릴리스 풀이 있거나 없어서 충돌 여부
'아직 완료되지 않은 쓰기 또는 빈 값'중간에 바로 읽도록 허용하거나 값이 완전히 쓰여질 때만 읽도록 허용합니다 .
선언하는 방법 :
원자가 기본값이므로
@property (retain) NSString *name;
AND 구현 파일
self.name = @"sourov";
세 가지 속성과 관련된 작업이
@property (retain) NSString *name;
@property (retain) NSString *A;
@property (retain) NSString *B;
self.name = @"sourov";
모든 속성은 병렬 적으로 (비동기 적으로) 작동합니다.
당신이 스레드에서 "이름"을 호출하는 경우 ,
과
당신이 전화하면 동시에
[self setName:@"Datta"]
스레드 B 에서
* name 속성이 비 원자 라면
그것이 원자가 아닌 것을 스레드 안전하지 않은 이유이지만 병렬 실행으로 인해 성능이 빠릅니다.
* name 속성이 원자 인 경우
스레드 안전이라는 이유 원자의 것으로 하고 그의는 그것은 읽기 - 쓰기 안전이라고하는 이유
이러한 상황 작업은 순차적으로 수행됩니다. 그리고 성능 저하
-비 원자 (Nonatomic)는 다중 스레드가 변수 (동적 유형)에 액세스하는 것을 의미합니다.
-비 원자 스레드 안전하지 않습니다.
-그러나 성능이 빠릅니다.
-Nonatomic은 기본 동작이 아니며 속성 속성에 비 원자 키워드를 추가해야합니다.
스위프트의 경우 스위프트 속성이 ObjC 의미에서 비원 자임을 확인합니다. 한 가지 이유는 속성 별 원자가 귀하의 요구에 충분한 지 여부를 생각하기 때문입니다.
참조 : https://forums.developer.apple.com/thread/25642
자세한 정보는 웹 사이트 http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html을 방문하십시오.
atomic
있다 하지 스레드 안전! 스레드 문제에 더 강하지 만 스레드 안전하지는 않습니다. 단지 "올바른"값 (바이너리 레벨)이라는 전체 가치를 얻을 수 있지만 비즈니스 논리에 대한 현재 및 "올바른"값임을 보장 할 수는 없습니다. 논리에 의해 유효하지 않음).
원 자성 원자 (디폴트 값)
원자가 기본값입니다. 아무 것도 입력하지 않으면 속성이 원 자성입니다. 원자 속성은 그 속성을 읽으려고하면 유효한 값을 얻습니다. 그 값이 무엇인지에 대해 보증하지는 않지만 정크 메모리뿐만 아니라 좋은 데이터를 얻을 수 있습니다. 이것이 할 수있는 것은 단일 변수를 가리키는 다중 스레드 또는 다중 프로세스가있는 경우 하나의 스레드가 읽고 다른 스레드가 쓸 수있는 것입니다. 동시에 충돌하면 리더 스레드는 변경 전 또는 변경 후 두 값 중 하나를 얻습니다. 원자가 제공하지 않는 것은 어떤 값을 얻을 수 있는지에 대한 보증입니다. 원자는 실제로 스레드 안전과 혼동되기 때문에 정확하지 않습니다. 다른 방법으로 스레드 안전을 보장해야합니다.
비 원자
반대로, 원자가 아닌 것은 아마도 "원자 적 일을하지 말라"는 것을 의미 할 것입니다. 당신이 잃어버린 것은 항상 무언가를 되 찾는다는 보장입니다. 쓰기 도중에 읽으려고하면 가비지 데이터를 다시 얻을 수 있습니다. 그러나 다른 한편으로는 조금 더 빠릅니다. 원자 속성은 값을 되 찾을 수 있도록 약간의 마법을 수행해야하기 때문에 조금 느립니다. 그것이 당신이 많이 접근하는 재산이라면, 당신은 그 속도 패널티가 발생하지 않도록 비 원자력으로 드롭 다운 할 수 있습니다. 접속하다
예의 https://academy.realm.io/posts/tmi-objective-c-property-attributes/
원자 속성과 비 원자 속성은 해당 Swift 속성 선언에 반영되지 않지만 가져온 속성이 Swift에서 액세스 될 때 Objective-C 구현의 원 자성 보장은 여전히 유지됩니다.
따라서 Objective-C에서 원자 속성을 정의하면 Swift에서 사용할 때 원자 속성으로 유지됩니다.
예의 https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c
진실은 그들이 스핀 속성을 사용하여 원자 속성을 구현한다는 것입니다. 아래와 같은 코드 :
static inline void reallySetProperty(id self, SEL _cmd, id newValue,
ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:NULL];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:NULL];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
_spin_lock(slotlock);
oldValue = *slot;
*slot = newValue;
_spin_unlock(slotlock);
}
objc_release(oldValue);
}
전체 혼란을 단순화하기 위해 뮤텍스 잠금을 이해하자.
이름에 따라 뮤텍스 잠금은 객체의 변경 성을 잠급니다. 따라서 클래스가 객체에 액세스하면 다른 클래스는 동일한 객체에 액세스 할 수 없습니다.
iOS에서는 @sychronise
mutex 잠금도 제공합니다. 이제는 FIFO 모드에서 작동하며 동일한 인스턴스를 공유하는 두 클래스의 흐름에 영향을 미치지 않습니다. 그러나 작업이 기본 스레드에있는 경우 UI를 보유하고 성능을 저하시킬 수 있으므로 원자 속성을 사용하여 객체에 액세스하지 마십시오.
원자 : NSLOCK을 사용하여 스레드를 잠그면 스레드 안전성이 보장됩니다.
비 원자 : 스레드 잠금 메커니즘이 없기 때문에 스레드 안전성을 보장하지 않습니다.
원자 속성 :-원자 속성으로 지정된 변수가 하나의 스레드 액세스 만 가지고 스레드 안전하고 성능 관점에서 우수하다는 것을 의미하면 기본 동작을합니다.
비 원자 속성 :-원자 속성이 할당 된 변수는 다중 스레드 액세스가 가능하고 스레드 안전하지 않고 성능 관점에서 느려질 때 기본 동작을 가지며 두 개의 다른 스레드가 동시에 변수에 액세스하려고 할 때 예기치 않은 결과가 발생합니다.