1:原子操作 - OSAtomic系列函数

iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件<libkern/OSBase.h>。不同线程如果通过原子操作函数对同一变量进行操作,可以保证一个线程的操作不会影响到其他线程内对此变量的操作,因为这些操作都是原子式的。因为原子操作只能对内置类型进行操作,所以原子操作能够同步的线程只能位于同一个进程的地址空间内。

2:锁 - NSLock系列对象

iOS平台下的锁对象为NSLock对象,进入锁通过调用lock函数,解锁调用unlock函数(因为iOS中大部分的线程同步类都继承自NSLocking协议,所以其加锁/解锁的操作基本都为lock/unlock函数),同一个NSLock对象成功调用lock函数后,在其显式unlock之前任何线程都不能再对此NSLock对象加锁,以达到互斥访问的目的。除了lock函数,对NSLock加锁的函数还包括tryLock以及lockBeforeDate函数,lock函数在成功加锁之间会一直阻塞,而tryLock会尝试加锁,如果不成功,不会阻塞,而是直接返回NO,lockBeforeDate则是阻塞到传入的NSDate日期为止。

除了NSLock,iOS还提供了NSRecursive、NSConditionLock类型的锁类型。NSRecursive与NSLock最大的区别就是NSRecursive是可重入的,也就是说一个线程可以对一个NSRecursive对象多次调用lock,只要解锁时调用相同次数的unlock函数便可。NSConditionLock是一种带有条件的锁对象,除了基本的lock与unlock函数,还提供了lockWithCondition以及unlockWithCondition,这两个函数接收整型类型的数据作为参数,只有当一个unlockWithCondition对象被调用时,对应的lockWithCondition才会正常返回。这种机制在需几多个线程顺序化的完成某个任务时比较有用,例程如下:

[plain] view plaincopy

除了显示的生成NSLock系列对象,还可以通过将代码放到@synchronized内来达到同步的目的,一段放入其内的代码,不同的线程是不能重入的例如:

NSLock系列对象都是可以具名的,也就是说,这些对象可以用于不同进程内部的线程的同步。

3:事件 - NSCondtion

NSConditon类型提供了wait与signal函数,分别代表了等待事件的操作以及触发事件的操作。除了wait函数,NSCondition还提供了waitUntilDate函数,其功能与NSLock中的lockBeforeDate大致相同,简要来说就是提供了一个带超时的wait函数。

虽然NSCondition与Windows环境下Event类型所完成的功能大致类似,但对一个熟悉Event类型的开发人员来说,NSConditon的行为会有点奇怪:

第一点:因为遵循NSLocking协议,所以NSCondition在触发与等待过程的前后要分别调用lock与unlock函数,前面提到过,当一个遵循NSLocking协议的对象调用lock后,其他的对此对象的lock调用都会阻塞。那么,如果两个线程A和B,A要触发事件,B接收事件,B线程在调用lock后,通过调用wait函数进入等待事件触发的状态,那么,A线程岂不是再也没有机会对这个事件进行触发了(因为此对象已经被B线程lock)?秘密就在于wait函数的调用,其实,在wait函数内部悄悄的调用了unlock函数,也就是说在调用wati函数后,这个NSCondition对象就处于了无锁的状态,这样A线程就可以对此对象加锁并触发该NSCondition对象。当一个事件被其他线程触发时,在wait函数内部得到此事件被触发的通知,然后对此事件重新调用lock函数,然后函数返回,而在函数外部,看起来好像接收事件的线程从来没有放开NSCondition对象的所有权,B线程直接由阻塞状态进入了触发状态。

第二点:当有多个线程进入阻塞状态,等待同一个AutoReset的Event对象被触发时,在Windows环境下唤醒哪一个线程是没有固定的顺序的,也就是说操作系统对唤醒哪一个线程不会提供任何的保证。而在iOS平台上,经过笔者测试,其被触发的顺序与,并且只与调用wait函数的顺序相关,与其他(比如线程优先级)条件没有关系。这一点在开发时需要进行额外的考虑。

第三点:wait函数并不是完全可信的。这一点比较让人蛋疼,也就是说wait返回后,并不代表对应的事件一定被触发了,因此,为了保证线程之间的同步关系,使用NSCondtion时往往需要加入一个额外的变量来对非正常的wait返回进行规避。具体示例代码如下:

这个timeToDoWork就是那个额外需要的变量,在NSCondition的使用中,这个变量是必不可少的。

NSConditon对象也是具名的,也就是说,其可于不同进程内部的线程同步。

iOS多线程编程:线程同步总结的更多相关文章

  1. IOS 多线程,线程同步的三种方式

    本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...

  2. Delphi多线程编程--线程同步的方法(事件、互斥、信号、计时器)简介

    更详细的可以参考:http://www.cnblogs.com/xumenger/p/4450659.html 或者参考之后的博客 四个系统内核对象(事件.互斥.信号.计时器)都是线程同步的手段,从这 ...

  3. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

  4. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

  5. iOS多线程编程

    废话不多说,直接上干货.先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD. 一.基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a com ...

  6. iOS多线程编程指南

    iOS多线程编程指南(拓展篇)(1) 一.Cocoa 在Cocoa上面使用多线程的指南包括以下这些: (1)不可改变的对象一般是线程安全的.一旦你创建了它们,你可以把这些对象在线程间安全的传递.另一方 ...

  7. C#并行编程-线程同步原语

    菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...

  8. 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)

    Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...

  9. MFC——9.多线程与线程同步

    Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中.多线程技术是提高程序性能的重要手段. 本文主要解说操作系统中程序.进程和线程之间的关系,并通过相互排斥对象和事件对象 ...

  10. Python并发编程-线程同步(线程安全)

    Python并发编程-线程同步(线程安全) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 线程同步,线程间协调,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直 ...

随机推荐

  1. OJ上 编译器 G++和C++的区别

    原文 :http://blog.csdn.net/febr2/article/details/52068357 编译时的差异: 编译器优化不同: 举个栗子: ①: a++ ②: ++a 从标准C的角度 ...

  2. 51NOD 1087 1 10 100 1000

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1087 暴力大法 #include<bits/stdc++.h> ...

  3. struts框架的运行原理和流程

    从此图中简单描述一下struts2的运行流程:1.客户端请求一个HttpServletRequest的请求,如在浏览器中输入http://localhost: 8080/bookcode/Reg.ac ...

  4. Ubuntu 14.04 禁用ipv6

    参考: 关闭IPV6,ubuntu 14.04 Ubuntu 14.04 禁用ipv6 1.检查ipv6是否开启: cat /proc/sys/net/ipv6/conf/all/disable_ip ...

  5. Springboot统一参数验证方式

    Springboot统一验证方式 在提供http api 接口形式的服务中,通过都会传递参数为一个对象.我们需要对这个对象的各个字段进行校验.来判断是否为合法值. 传统的方式为自己获取每个字段的值,自 ...

  6. JS进阶系列之this

    在javascript中,this的指向是在执行上下文的创建阶段确定的,其实只要知道不同执行方式下,this的指向分别是是什么,就能很好的掌握this这个让人摸不透的东西. 一.全局执行 全局执行又分 ...

  7. 《A_Pancers》第二次作业 基于Android系统的音乐播放系统项目开题报告

    小组名 N A B C D 总分 Just_Do_IT! 8 8 9 9 8 42 Miracle-House 8 8 7 8 8 39 ymm3  9 8 8 8 8 41 Spring_Four  ...

  8. Thunder团队Final版本控制

    Final版本控制报告 团队介绍:Thunder Check in次数 :6次. check in log(时间.人员.message.动机.其他解释) 代码贡献量.代码贡献比例以及代码作用 git链 ...

  9. Linux 之 ./configure --prefix 命令

    参考 http://blog.sina.com.cn/s/blog_406127500101dsmy.html 源码的安装一般由3个步骤组成:配置(configure).编译(make).安装(mak ...

  10. Codeforces 916C - Jamie and Interesting Graph

    916C - Jamie and Interesting Graph 思路:构造. 对于1到n最短路且素数,那么1到n之间连2 对于最小生成树,找一个稍微大点的素数(比1e5大)构造一个和为这个素数的 ...