Object’s retain count in influenced by ‘@synchronized’

I found that the retain count of an object created inside the @synchronized block will be difference with an object created outside the @synchronized block.

Case 1: create inside the @synchronized block, the retain count of observer is 2:

- (NSUInteger)mv_observeKeyPath:(NSString *)keyPath                   withBlock:(MVKVOBlock)block                     options:(NSKeyValueObservingOptions)options {     @synchronized (lock) {         MVKVOProxy *observer = [MVKVOProxy observerWithTarget:self keyPath:keyPath block:block];         // po [observer performSelector:@selector(retainCount)] is 2         [self addObserver:observer forKeyPath:keyPath options:options context:NULL];         return observer.observerID;     } } 

Case 2: create outside the @synchronized block, the retain count of observer is 1:

- (NSUInteger)mv_observeKeyPath:(NSString *)keyPath                   withBlock:(MVKVOBlock)block                     options:(NSKeyValueObservingOptions)options {     MVKVOProxy *observer = [MVKVOProxy observerWithTarget:self keyPath:keyPath block:block];     @synchronized (lock) {         // po [observer performSelector:@selector(retainCount)] is 1         [self addObserver:observer forKeyPath:keyPath options:options context:NULL];         return observer.observerID;     } } 

I know an object return by a method will be wrapped with objc_retainAutoreleasedReturnValue and objc_retainAutoreleasedReturnValue. It is used for optimization with useless [[obj autorelase] retain].

The method defination of objc_retainAutoreleasedReturnValue is:

id objc_retainAutoreleasedReturnValue(id obj) {     if (acceptOptimizedReturn() == ReturnAtPlus1) return obj;      return objc_retain(obj); } 

I have debugged and stepped into assembly code and found that, in case 2 objc_retain will not be called.

The method objc_retainAutoreleasedReturnValue of is:

id objc_retainAutoreleasedReturnValue(id obj) {     if (acceptOptimizedReturn() == ReturnAtPlus1) return obj;      return objc_retain(obj); } 

In both cases, objc_retain will be called.

Therefore, in case 1, the method call stack is [[observer autorelaase] retain], in case 2, the method call stack is [observer autorelaase]. Is it strange? Why does @synchronized has effect against ARC?