火锅加糖

仗剑行千里,微躯敢一言。
曾为大梁客,不负信陵恩。

Vno Jekyll is a port of my Ghost theme vno.


Download the theme

Ios 关键字atomic和nonatomic的区别

###atomic和nonatomic的区别— layout: post title: Sample Post date: 2018-06-04 17:42:24.000000000 +09:00 —###

atomic

 1. 默认的
 2. 会保证CPU能在别的线程来访问这个属性之前,先执行完当前操作
 3. 速度不快,因为要保证操作整体完成

nonatomic

 1. 不是默认的
 2. 更快
 3. 线程不安全(如有两个线程访问同一个属性,会出现无法预料的结果)
iOS在声明属性时,默认会是atomic,当然如果在创建属性之后选择自己写setter/getter方法,那么atomicnonatomic关键字将没有意义.

对于atomic关键字修饰的属性而言,系统生成的gette/setter方法会保证在进行get/set操作时的完整性,不会受到其余线程的影响,可以保证读写操作的安全性.例如:线程A的getter方法运行到一半,线程B调用了setter方法,此时线程A的getter方法还是能获取到一个完好无损的对象,这是一个串行的操作.但是如果是nonatomic修饰的属性,当多个线程同时对属性进行读写操作,会进行并发访问,可能会产生不可预知的问题,例如crash.

atomic可以保证属性的读写是安全的,但是atomic无法保证值的时效性,例如:线程A调用了getter,与此同时线程B和C都调用的setter,此时A get到的值可能是B set的值,也可能是C set的或者最初的值,因为无法确定是哪个线程先执行完成,但是会保证一定会有值.

保证数据的完整性,这是多线程变成最大的挑战之一,往往需要借助其余的手段

代码: nonatomic修饰属性生成的getter/setter方法

- (UITextField *) userName {
	return userName;
}

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

atomic修饰属性生成的getter/setter方法

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

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

关于@sychronized同步锁,在atomic关键字修饰后创建的setter/getter方法中并不是使用的@sychronized同步锁,因为同步锁只能保证当前线程的运行完整性,无法保证具体是哪一个线程,所以还是会存在atomic本身的问题,所以atomic真正使用的是自旋锁,其实我们在开发中也可以通过GCD的栅栏过滤来模拟自旋锁,达到同样的效果.

最近的文章

Ios 常见的属性关键字

iOS在声明属性时,在ARC环境下常用的关键字基本上有:readonly、readwrite、nonatomic、atomic、strong、retain、assign、weak、copy、static、const、extern等,接下来对这些关键字的异同进行分析。readonly和readwrite关键字从字面意思可以很清楚的了解其应用,readonly只读和readwrite可读写。readwrite是属性创建时的默认属性,同时拥有setter、getter方法,而readonly只生...…

继续阅读
更早的文章

Git Git常用命令总结

###Git常用命令总结—layout: posttitle: Sample Postdate: 2018-04-14 15:32:24.000000000 +09:00—基本命令 git config --global user.name "Your Name"设置你的仓库用户名(用于标识提交者) git config --global user.name "email@example.com"设置你的仓库邮箱(用于标识提交者) git init初始化一个git仓库 ...…

继续阅读