进程基本概念


  • 进程就是一个正在运行的一个应用程序;
  • 每一个进度都是独立的,每一个进程均在专门且手保护的内存空间内;
  • iOS是怎么管理自己的内存的,见博客:博客地址
  • 在Linux系统中,想要新开启一个进程是一件非常简单的事情只需要一句话:fork(),在fork()之后就会包含两个进程,此时可以根据返回的PID来判断是子进程还是父进程;
  • iOS中是一个非常封闭的系统,每一个App(一个进程)都有自己独特的内存和磁盘空间,别的App(进程)是不允许访问的(越狱不在讨论范围);
  • 所以,在iPhone中下载了两种音乐播放器,下载的音乐歌曲却是不能共享的!跟安卓完全不同!——有好有坏吧!
  • 如果想学习进程方面的知识,我觉得还是看看Linux对进程的描述,比如进程间的通信(管道、内存共享、实用信号量防止资源抢夺等)。

线程基本概念


- 线程是CPU调度的最小单元;
- 线程的作用:执行app的代码;
- 一个进程(App)至少有一个线程,这个进程叫做主线程;

线程和进程的关系

  • 进程和应用程序的关系:进程为应用程序开辟内存空间;
  • 线程和应用程序的关系:线程执行应用程序的代码;
  • 进程和线程之间的关系:进程是由线程组成的、一个进程理论上可以有很多个线程、但至少有一个主线程;

线程

在iOS中进程相关的操作并不是很多,常见的就App之间相互调用,苹果公司将这些操作都封装在了UIApplcation这个类中了。


为什么要使用多线程

CPU -> 进程 -> 线程;

如果是在Linux系统中,在讨论为什么在使用多进程时,是针对多进程考虑的,因为Linux支持多进程程序;而iOS开发中,仅仅就是真对一个(App)进程来开发的;

  1. 方便的通信和数据交换

    多进程程序结构和多线程程序结构有很大的不同;

    对不同进程来说,它们具有独立的数据空间,要 进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然, 由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用, 这不仅快捷,而且方便。

  2. 更高效的利用 CPU

    大多数操作系统是根据时间片轮转调度,在Linux/Unix中,CPU的调度事件是100ms;而线程是CPU最小的调度单元,也就是说当开启一个新线程时,CPU在自己的调度链表中去循环调度这个线程;如果一个线程没有,那么CPU就会休息;所以说,多线程能够适当提高CPU的利用率!当然CPU调用时并非这么简单,其中会包含调度的优先级、中断等来保证CPU调度是优化的!

    所以,在讨论为什么要使用多线程时,如果不说针对多进程而言是那就是没有没有参考对象。

  3. 当然,程序中并非开启越多的线程越好,首先线程需要消耗内存,主线程1M、子线程是512K;

    其次、线程越多,CPU的线程链表就越长,执行效率会变慢!适当的利用多线程!在iOS 中,苹果公司也为我们封装一个类`NSOperation`


多线程在iOS开发中的应用

  • 一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”

  • 主线程的主要作用

  • 显示\刷新UI界面
  • 处理UI事件(比如点击事件、滚动事件、拖拽事件等)

  • 主线程的使用注意

  • 别将比较耗时的操作放到主线程中
  • 耗时操作会卡住主线程,严重影响UI的流畅度,极差的用户体验!

在iOS的中多线程的实现方法

四种实现方式Threads、NSthread、NSOperation、GCD,使用频率由低到高!


  1. POSIX Threads

    • 众多软件供应商都为自己产品实现多线程库专有版本。这些线程库实现彼此独立并有很大差别,导致程序员难以开发可移植的多线程应用程序,因此必须要确立一个规范的编程接口标准来充分利用多线程所提供的优势,POSIX -Threads 就是这样一个规范多线程标准接口。

    • POSIX Threads(通常简称为Pthreads)定义了创建和操纵线程的一套 API 接口,一般 用于 Unix-like POSIX 系统中(如 FreeBSD、GNU/Linux、OpenBSD、Mac OS 等系统)。

    Pthreads 接口可以根据功能划分四个组:

    • 线程管理
    • 互斥量
    • 条件变量
    • 同步

Threads.1. 程管理线

程管理包含了线程的创建、终止、等待、分离、设置属性等操作。
每个线程都有从创建到终止的生命周期。
创建线程
在进程中创建一个新线程的函数是 pthread_create(),原型如下:
```
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg); ```
说明:线程被创建后将立即运行。
如果pthread_create()调用成功,函数返回0,否则返回一个非0的错误码
参数说明:
thread用指向新创建的线程的ID;
attr用来表示一个封装了线程各种属性的属性对象,如果attr为NULL,新线程就 使用默认的属性,13.3.4 节将讨论线程属性的细节;
start_routine是线程开始执行的时候调用的函数的名字,start_routine函数有一个有 指向 void 的指针参数,并有 pthread_create 的第四个参数 arg 指定值;start_routine 函数返回一个指向 void 的指针,这个返回值被 pthread_join 当做退出 状态处理;
arg为参数start_routine指定函数的参数。
2. 终止线程
void pthread_exit(void *retval);

线程安全

多线程编程环境中,多个线程同时调用某些函数可能会产生错误结果,这些函数称为非线程安全函数。如果库函数能够在多个线程中同时执行并且不会互相干扰,那么这个库函数 就是线程安全(thread-safe)函数;
  • Threads.2. 互斥量

    在操作系统中有许多共享资源不允许用户并行使用,例如手机的通话,在通话过程中,不能同时去接两个电话,香这种共享设备被称为“排它性资源”,因为它一次只能由一个执行流访问。执行流必须以互斥的方式执行访问排它性资源的代码。

    临界区是必须以互斥方式执行的代码段,也就是说在临界区的范围内只能有一个活动的执行线程。

    互斥量(Mutex),又称为互斥锁,是一种用来保护临界区的特殊变量,它可以处于锁定(locked)状态,也可以处于解锁(unlocked)状态:

    如果互斥锁是锁定的,就是一个特定的线程持有这个互斥锁;

    如果没有线程持有这个互斥锁,那么这个互斥锁就处于解锁状态。

    每个互斥锁内部有一个线程等待队列,用来保存等待该互斥锁的线程。当互斥锁处于解锁状态时,一个线程试图获取这个互斥锁时,这个线程就可以得到这个互斥锁而不会阻塞;

    当互斥锁处于锁定状态时,一个线程试图获取这个互斥锁时,这个线程将阻塞在互斥锁的等 待线程队列内。

    互斥量是最简单也是最有效的线程同步机制。程序可以用它来保护临界区,以获得对排它性资源的访问权。

    另外,互斥量只能被短时间地持有,使用完临界资源后应立即释放锁。

        pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&mylock);
    临界区代码
    pthread_mutex_unlock(&mylock);

Threads.3. 条件变量

在多线程编程中仅使用互斥锁来完成互斥是不够用的,如以下情形:

假设有两个线程 t1 和 t2,需要这个两个线程循环对一个共享变量 sum 进行自增操作, 那么 t1 和 t2 只需要使用互斥量即可保证操作正确完成,线程执行代码如所示:

```
pthread_mutex_t sumlock= PTHREAD_MUTEX_INITIALIZER;
void * t1t2(void) {
thread_mutex_lock(&sumlock);
sum++;
pthread_mutex_unlock(&sumlock); }
```
如果这时需要增加另一个线程 t3,需要 t3 在 count 大于 100 时将 count 值重新置 0 值, 那么可以 t3 可以实现如下:
```
void * t3 (void) { pthread_mutex_lock(&sumlock);
if (sum >= 100) {
sum = 0;
pthread_mutex_unlock(&sumlock);
} else {
pthread_mutex_unlock(&sumlock);
usleep(100);
}
}
```
以上代码存在以下问题:
1) sum 在大多数情况下不会到达 100,那么对 t3 的代码来说,大多数情况下,走的是 else分支,只是 lock 和 unlock,然后 sleep()。这浪费了 CPU 处理时间。
2) 为了节省 CPU 处理时间,t3 会在探测到 sum 没到达 100 的时候 usleep()一段时间。 这样却又带来另外一个问题,亦即 t3 响应速度下降。可能在 sum 到达 200 的时候,t3 才会 醒过来。
这样时间与效率出现了矛盾,而条件变量就是解决这个问题的好方法。 在Threads这种场景就需要用等待和通知去解决!
条件等待函数有 pthread_cond_wait()pthread_cond_timedwait()和两个条件通知函数有 pthread_cond_signal()和 pthread_cond_broadcast()函数; 其实这种场景在iOS开发中,就是进程中有相互依赖的关系,A执行完毕,B才能执行;NSOperation中就可以添加依赖,使得A完成之后B才能去执行; 如果在不同的队列中,那么就需要用GCD的dispatch_group_t(队列)组去解决!
那么我觉得dispatch_group_t就是对Threads的通知等待的封装。

iOS-线程&&进程的深入理解的更多相关文章

  1. 线程&进程&协程

    线程 线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.Threading用 ...

  2. python--再看并行之协程线程进程

    1.gevent协程适合I/O密集,不适合CPU密集. 3.gevent协程无法发挥多核优势,事实上,协程只是以单线程的方式在运行. 3.子程序就是协程的一种特例 项目实际应用 from gevent ...

  3. 15.python并发编程(线程--进程--协程)

    一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完 ...

  4. Python 多线程、多进程 (三)之 线程进程对比、多进程

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.多线程与多进 ...

  5. 线程&进程

    扯淡的yuan 并发&并行 并发:是指系统具有处理多个任务(动作)的能力. 并行:是指系统具有 同时 处理多个任务(动作)的能力. 同步&异步 同步:当进程执行到一个IO(等待外部数据 ...

  6. iOS 线程操作库 PromiseKit

    iOS 线程操作库 PromiseKit 官网:http://promisekit.org/ github:https://github.com/mxcl/PromiseKit/tree/master ...

  7. python之并发编程(线程\进程\协程)

    一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...

  8. 关于CPU核心,线程,进程,并发,并行,及java线程之间的关系

    前言:作为一个转行java的小白,一直搞不清楚java中的多线程.于是来梳理一下关于CPU核心,线程,进程,并发,并行,及java线程之间的关系, 1.CPU角度来看: 我们以Intel的Core i ...

  9. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

随机推荐

  1. python-经典类和新式类区别

    经典类和新式类区别 Eg: class A(object):    def x(self):        print('A')class B(A):    def x(self):        p ...

  2. 黑马程序员_毕向东_Java基础视频教程——位运算符(随笔)

    位运算符 左移和右移 左移 左移越移越大. 往左移几位就相当于这个数乘于2的几次方 3 << 2 --> 3 * 2^2 = 3 * 4 = 12 3 << 3 --&g ...

  3. 一文带你学会国产加密算法SM4的vue实现方案

    前言 上篇文章我们介绍了国产SM4加密算法的后端java实现方案.没有看过的小伙伴可以看一下这篇文章. https://www.cnblogs.com/jichi/p/12907453.html 本篇 ...

  4. 当Tomcat遇上Netty

    故事背景 嘀嘀嘀~,生产事故,内存泄漏! 昨天下午,突然收到运维的消息,分部某系统生产环境内存泄漏了,帮忙排查一下. 排查过程 第一步,要日志 分部给到的异常日志大概是这样(鉴于公司规定禁止截图禁止拍 ...

  5. 从X86指令深扒JVM的位移操作

    概述 之所以会写这个,主要是因为最近做的一个项目碰到了一个移位的问题,因为位移操作溢出导致结果不准确,本来可以点到为止,问题也能很快解决,但是不痛不痒的感觉着实让人不爽,于是深扒了下个中细节,直到看到 ...

  6. Spark Streaming 整合 Flume

    Spark Streaming 整合 Flume ​ 一.简介二.推送式方法        2.1 配置日志收集Flume        2.2 项目依赖        2.3 Spark Strea ...

  7. springmvc+mybatis 实现登录、注册、邮件激活等功能

    原创作品, 转载请注明来源

  8. 阿里云服务器 ECS Ubuntu系统下PHP,MYSQL,APACHE2的安装配置

    1.系统更新,必须更新,否则有些软件会找不到. apt-get update apt-get upgrade 2.安装mysql sudo apt-get install mysql-server 3 ...

  9. jQuery下实现等待指定元素加载完毕(可改成纯js版)

    http://www.poluoluo.com/jzxy/201307/233374.html 代码如下: jQuery.fn.wait = function (func, times, interv ...

  10. Gym101630C Connections

    题目大意: 给出一个\(n\)个点\(m\)条边的有向图,无自环无重边.要求把这个图进行删边,直到只剩下\(2n\)条边,使得图中每个点都可以相互连通. 知识点: DFS 解题思路: 从点\(1\)出 ...