一、接上一篇《nonatomic 带来的线程安全问题》,这里继续详细讨论属性各种类型与线程安全的关系

  1)影响线程安全的属性类型,nonatomic,atomic,weak

@property (atomic, strong)   TestObject  *obj;
@property (nonatomic, strong) TestObject *obj;
@property (atomic, weak) TestObject *obj;
@property (nonatomic, weak) TestObject *obj;

  上面有4种属性的定义,在遇到下面的代码的时候

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        for (int i = 0; i < 10000; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// self.obj = [[TestObject alloc] init]; });
} });

  第1种定义不会crash,这是符合atomic的标准写法,通过setter、和getter访问器访问变量。

  第2种定义会crash,因为nonatomic定义的属性,在setter中也没有加锁,所以多线程访问之下会出现问题。

  第3种和第4种都不会crash,主要原因是,将对象赋值给weak指针的时候,都不会对对象的引用计数进行改变,

    此外weak对象添加weak引用表标记的时候,还会对该对象进行加锁,因此杜绝了多线程问题。但是多线程访问之下,最好还是atomic。

  2)如果一个对象是atomic,并且是通过下划线,实例变量访问的时候还是会crash。

    因为所谓atomic是加在getter和setter中的,我们比较一下下面属性的定义翻译成汇编之后的不同

    

@interface ViewController ()

@property (atomic, strong)   TestObject*  x;
@property (nonatomic, strong) TestObject* y; @end

  

  对应汇编:

注意最后调用的存储方法,一个是加锁版本,一个未加锁版本。在getter中,一个是通过方法返回的,一个是通过指针的偏移

二、总结

  iOS中的属性和线程安全需要通过下面的方式保证:

  1) 使用atomic定义属性,同时使用getter和setter能够保证这个对象本身的引用计数线程安全问题,也就是避免多线程导致的错误释放。

  2) 使用weak定义属性,避免多线程中对引用计数的操作。

  保证了属性的原子性性访问,并不代表业务上面的线程安全问题,业务上的线程安全问题。

  业务的线程安全:

  1)加锁,NSLock,递归所,自旋锁,读写锁,内存屏障

  2)串行队列保证任务不会交替执行

  3)使用单线程+异步的模型

Objetive-C 属性和线程安全的更多相关文章

  1. 线程的属性和 线程特定数据 Thread-specific Data

    一.posix 线程属性 POSIX 线程库定义了线程属性对象 pthread_attr_t ,它封装了线程的创建者可以访问和修改的线程属性.主要包括如下属性: 1. 作用域(scope) 2. 栈尺 ...

  2. C# 的界面控件属性修改线程安全问题

    今天在实验delegate与thread 在初步的实验结束后,因为原来的delegate只有一个函数会被调用,感觉没有达到delegate的极致,所以又重新自己定义了一个delegate,在另一个线程 ...

  3. 线程属性总结 线程的api属性

    http://blog.csdn.net/zsf8701/article/details/7842392 //线程属性结构如下:typedef struct{ int etachstate; //线程 ...

  4. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  5. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  6. pthread_attr_t 线程属性(二)

    一.函数: 1.线程属性的初始化与销毁:#include <pthread.h>int pthread_attr_init(pthread_attr_t *attr);int pthrea ...

  7. Linux多线程实践(3) --线程属性

    初始化/销毁线程属性 int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *att ...

  8. 线程属性 pthread_attr_t

    参考资料: https://blog.csdn.net/hudashi/article/details/7709413 Posix线程中的线程属性pthread_attr_t主要包括scope属性.d ...

  9. Unix线程概念、控制原语、属性

    线程: 线程基础概念: 线程在Linux中又称轻量级进程.而且它和进程都有PCB(进程控制块).可是差别是进程的虚拟地址空间是独享的,也就是每一个进程都有自己的虚拟地址空间.可是线程的PCB是共享的, ...

  10. UNIX环境编程学习笔记(27)——多线程编程(二):控制线程属性

    lienhua342014-11-09 1 线程属性概括 POSIX 线程的主要属性包括 scope 属性.detach 属性.堆栈地址.堆栈大小.优先级.在头文件 pthread.h 中定义了结构体 ...

随机推荐

  1. js es6 Iterator

    1.遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员). 2.Iterator ...

  2. tensorflow如何切换CPU和GPU

    import os if Bert_Use_GPU: os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' #使用GPU0,1 else: os.environ['CU ...

  3. 力扣455(java&python)-分发饼干(简单)

    题目: 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干. 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j,都有 ...

  4. Flink SQL 1.11 on Zeppelin 平台化实践

    简介: 鉴于有很多企业都无法配备专门的团队来解决 Flink SQL 平台化的问题,那么到底有没有一个开源的.开箱即用的.功能相对完善的组件呢?答案就是本文的主角--Apache Zeppelin. ...

  5. DTCC 2020 | 阿里云梁高中:DAS之基于Workload的全局自动优化实践

    简介: 第十一届中国数据库技术大会(DTCC2020),在北京隆重召开.在12.23日性能优化与SQL审计专场上,邀请了阿里巴巴数据库技术团队高级技术专家梁高中为大家介绍DAS之基于Workload的 ...

  6. [FAQ] WebStorm/PHPStorm:设置 HTML/JavaScript/PHP 注释缩进行为,代码片段

    [注释行为] Preferences -> Code Style 选择语言后,找到 Wrapping and Braces, 取消 Comment at first column. 如果是HTM ...

  7. dotnet CBB 为什么决定推送 Tag 才能打包

    通过推送 Tag 才打 NuGet 包的方法的作用不仅仅是让打包方便,让打包这个动作可以完全在本地执行,无需关注其他系统的使用步骤.更重要的是可以强制每个可能被安装的 NuGet 包版本都能有一个和他 ...

  8. 实验8 #第8章 Verilog有限状态机设计-3 #Verilog #Quartus #modelsim

    3. 状态机A/D采样控制电路 3.1 目标:用状态机控制ADC0809实现数据采集. 3.2 ADC0809简介 (1)ADC0809是8位A/D转换器,片内有8路模拟开关,可控制8个 模拟量中 的 ...

  9. 【web安全】隐藏nginx头文件信息

    摘要 Nginx作为开源web中间件,被广泛应用.因此源编译或者yum安装,都会带有其原有的nginx版本.很容易被针对,因此,通过修改nginx的源码.隐藏nginx版本和头部信息,保障nginx的 ...

  10. RocketMQ 事件驱动:云时代的事件驱动有啥不同?

    前言: 从初代开源消息队列崛起,到 PC 互联网.移动互联网爆发式发展,再到如今 IoT.云计算.云原生引领了新的技术趋势,消息中间件的发展已经走过了 30 多个年头. 目前,消息中间件在国内许多行业 ...