Objective-C 中 getter 有保证原子性( atomic)的必要吗?(换句话说 getter 有保证线程安全的必要吗)

2015-12-05 19:02:45 +08:00
 UtopiaCHN

@property 设置 atomic 时,同时对 setter 和 getter 生效。 setter 作用是设置值,保证线程安全可以理解。因为如果 A 线程在设值,那么后来的 B 线程应该等待 A 线程设置完成后再去设置。但是 getter 的作用是获取值,好像没有保证线程安全的必要吧?直接获取不就好了。

2607 次点击
所在节点    iDev
11 条回复
11
2015-12-05 19:19:22 +08:00
atomic 不保证线程安全
UtopiaCHN
2015-12-05 19:21:10 +08:00
@11 atomic 不保证整个对象的线程安全,但是它保证 setter 和 getter 各自的线程安全啊
11
2015-12-05 19:25:21 +08:00
@UtopiaCHN getter 的话,如果在两个线程都进行 getter ,那不能保证获取的数据一致啊
UtopiaCHN
2015-12-05 19:27:09 +08:00
@11 你是指有另一个线程在 setter 的时候吗?
11
2015-12-05 19:29:56 +08:00
@UtopiaCHN 对呀
UtopiaCHN
2015-12-05 19:34:33 +08:00
@11 如果 A 线程在 getter ,然后 B 线程去 setter ( A 线程直到 B 线程结束后才结束),那么 A 线程得到的是 B 线程设置之前还是之后的值呢
jjgod
2015-12-05 19:59:09 +08:00
@UtopiaCHN: 首先, getter 和 setter 是名词,不要把它们作动词用, get 和 set 才是动词,相信你小学英语学过。

至于你的问题, atomic 是不作这种保证的,它只保证得到的不是 B 线程设置了一半的值。比如假设一个 nonatomic 的 property 返回一个 CGPoint , B 线程设置了这个 point 的 .x 就切换回 A 线程了, A 线程最后返回的就可能是一半新的 .x 和一半旧的 .y , atomic 避免的是这种情况,保证你要么得到的是 B 设置前的那个 CGPoint ,要么是设置后的。
UtopiaCHN
2015-12-05 20:20:57 +08:00
@jjgod 非常感谢。 getter 和 setter 虽然是名词容器的意思,但是它们还是要完成相应的操作。你的解释完全符合原子性的定义。我的理解是不是错误的--“如果 A 线程在设值,那么后来的 B 线程应该等待 A 线程设置完成后再去设置。”,我理解的好像是加锁的意思,按照我的理解,不能同时有两个线程并发访问 setter 和 getter ,事实上是可以并发访问的对吗?
UtopiaCHN
2015-12-05 20:26:40 +08:00
@jjgod 大神你在 Apple 工作啊,好厉害,膜拜。
UtopiaCHN
2015-12-05 20:35:04 +08:00
@jjgod 那个应该是访问器,写错了。如果只是单纯的原子性,那么这好像不属于线程安全吧?也就是说 atomic 不能保证 setter 和 getter 的线程安全,只有加锁才可以。
jjgod
2015-12-05 20:46:55 +08:00
看这里的第一个和第二个回复吧: http://stackoverflow.com/questions/588866/whats-the-difference-between-the-atomic-and-nonatomic-attributes

比如这个等价为 atomic property 生成代码的例子:

- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}

- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName release];
userName = [userName_ retain];
}
}

比如 A 线程在先执行到 `UITextField *retval = nil` 这一步,切换到线程 B ,然后线程 B 执行完了跳回线程 A ,那么 A 是会读取到新的 userName instance variable 并返回的,但是假如一开始 A 是执行到 `return retval` 之前再切换到 B 呢,返回的就还是 B 设置前的 userName 值。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/241392

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX