[Objective-C] 프로퍼티의 atomic / nonatomic 속성

Objective-C에서 사용하는 프로퍼티(@property)는 알고보면 엄청나게 중요하더라. 이 프로퍼티를 선언할 때 속성을 지정하는데, 그 중에 nonatomic 이라고 거의 대부분의 객체 타입의 프로퍼티에는 명시해주는데, 이에 대해서 속시원히 설명해주는 글을 찾기가 힘들었다. 물론 멀티스레드 처리에서 해당 값을 안전하게 접근할 수 있도록 해주는 내용이고, 그게 별로 필요가 없으니 보통은 명시적으로 nonatomic으로 쓴다고는 하지만… 암튼 나름대로의 설명은 아래와 같다(…고 본다.)

OS나 프로그래밍에서 ‘atomic’이라는 말은 ‘중단되지 않는다’는 의미를 가진다. 즉 atomic한 함수는 그 전체가 실행되는 동안 중단되거나 CPU에 의해 스와핑되지 않는다.

무슨 말인고 하니, CPU는 한 번에 한 가지 일만 처리하는데, 많은 OS에서는 멀티스레딩을 지원한다. 이는 ‘시분할’이라는 기술에 의해서 아주 짧은 시간동안 운영체제가 각기 다른 프로세스에게 번갈아가면서 CPU의 사용 권한을 허락하기 때문이다. 워낙의 짧은 단위로 시간을 쪼개어 사용하기 때문에 사람이 인지하기에는 여러 가지 프로세스가 동시에 일을 처리하는 것 처럼 보일 뿐이다. (사실상 멀티 스레드는 일종의 잔상을 이용한 환영과 같은 술수이다.)

이를 위해 CPU 스케줄러는 어떤 프로세스의 동작 중에 이를 중지하고 다른 프로세스에게 CPU 사용 권한을 넘기는 것이 가능하다. (또 이렇게 하고 있다.) 따라서 두 개의 프로세스가 동시에 참조하는 변수를 업데이트하는 동작을 수행하기 위해서는 이 과정이 ‘atomic’하게 처리되어야 한다.

Objective-C에서 어떤 프로퍼티를 두 개의 스레드가 참조하고 있는 상황에서 이 프로퍼티의 접근자 메서드가 atomic 하지 않다면 한쪽 스레드에서는 A라는 값을 B라는 값으로 변경했는데, 다른 쪽에서는 그 때 새로 업데이트된 B라는값이 아닌 A라는 값으로 읽어가게 되는 문제가 생길 수 있다. 혹은 A값을 읽어야 하는데 읽는 중간에 B값으로 변경되어 문제가 발생할 수도 있을 것이다.

이런 경우에는 해당 프로퍼티를 atomic으로 설정해야 한다. 하지만 atomic으로 설정된 프로퍼티의 setter/getter 메서드는 lock을 사용하여 다중 스레드에 대해 안전하게 처리가되는데, 이 경우는 일반적인 경우에는 고려할 필요가 없으며 성능을 저하시킬 수 있으므로 대부분의 프로퍼티 선언에서는 명시적으로 nonatomic으로 선언한다. (Objective-C에서는 atomic이 디폴트로 설정된다.)