你真的了解并发编程吗?

简介: 1、进程和线程a)进程:是系统进行资源分配和调度的基本单位 i.每一个php脚本被运行都会开启一个进程 1. 在nginx:php-fpm 2. 在apache:CGIb)进程包含线程,线程是我们程序的一个执行单元,负责执行

1、进程和线程


a)进程:是系统进行资源分配和调度的基本单位
    i.每一个php脚本被运行都会开启一个进程
        1. 在nginx:php-fpm
        2. 在apache:CGI
b)进程包含线程,线程是我们程序的一个执行单元,负责执行
复制代码


2、PHP多线程开发


a)概念:是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能
b)原理:在一个php进程下,开启多个线程来执任务,提高执行效率
    i.同一件事情,一个人做和十个人做效率是不一样的,多线程就是这个原理
        1.例子:十件衣服,每件衣服洗干净平均需要5-10分钟,那么一个人去洗就需要一百分钟才能把所有的衣服洗完,那么如果十个人一起洗,每人一件,那么洗完这十件衣服的事件就是这十个人中洗的最慢的那个人所耗费的事件。
c)实现:php使用pthreads扩展,pthreads是基于c编写的php扩展,用于操作计算机的线程
    i.创建一个类 并且继承 Thread 类,并实现以下方法
        1.Run():编写多线程执行的业务代码
        ii.Start():开启多线程,并执行run中的任务
        iii.IsRunning():判断线程是否执行结束
        iv.Join:用于获取线程执行的结果
d)缺点:
    i.内存占用
    ii.线程的开启执行关闭需要消耗系统资源
    iii.线程默认共享内存中的数据,所以多线程是不安全的,这也是为什么php的pthreads扩展需要线程安全的版本,线程安全的版本会屏蔽线程之间的内存向
    iv.内存共享就代表着内存的抢占,需要引入互斥锁的机制,实现内存的管理,当又一个线程在访问内存时,其他的线程不允许访问
e)应用场景:
    i.多线程并发处理:
        1.同时执行多个任务,提高执行效率,获取返回结果
        2.场景:网络请求、本地文件I/O、大数据处理
    ii.具体实现业务:爬虫采集、文件读写日志
复制代码


3、PHP生成器


a)概念:实现对象的迭代,减少内存消耗
b)原理:通过实现php中的Iterator接口并实现接口内的方法:
    i.Rewind:重置对象指针
    ii.Next:移动对象指针到下一位
    iii.Current:获取当前指针的value
    iv.Key:获取当前指针的key
    v.Vaild:验证迭代的条件是否满足
    vi.实现对象的迭代,程序获取的是这个生成器的对象,在内存中只占用一个对象的空间,通过迭代来更新对象中的值,从而减少内存消耗
c)应用:在函数中使用yield关键字,再调用这个函数时返回的不再函数的执行结果,而是生成器对象,我们可以通过foreach遍历这个对象,每一次遍历会获取到生成器中yield后面的value,并且生成器中在yield位置暂停,下一次循环从暂停位置继续执行
复制代码


网络异常,图片无法展示
|

d)场景:
    i.大文件读写,减少内存消耗
复制代码


4、协程:


a)原理:协程小于线程,不同的是协程不依靠系统的调度,而是通过代码实现多任务快速切换,这个切换的过程无法感知,感官上是同时进行的,其实是串行执行的,因为不需要系统的调蓄,所以切换速度特别快消耗资源特别少,又可以提高执行的效率
    i.并行:一个单核的CPU同一之间只能执行一个任务,如果是多核可以同时执行多个任务,从而提高执行效率
    ii.并发:单核通过快速切换任务,释放与接收CPU控制权,实现多任务切换并发执行
b)实现:通过php生成器+任务管理器+调度器实现协程
c)应用场景:
    i.网络请求、I/O请求、提高系统吞吐量与执行效率
    ii.因为协程占用系统资源小,可以处理更多请求,提高系统的吞吐量
复制代码


5、Go的协程开发(gorountine)并发编程


a)概念:gorountine原理就是协程,只不过这些协程的调度go已经在内部实现了,包括垃圾回收,任务管理,调度,所以我们开发不需要管协程的内部实现,只需要关注业务开发就可以,go从语言层面就实现了并发
b)原理:多任务快速切换,不需要操作系统调度,可以通过管道(channel)实现通讯
c)实现:
    i.使用go的协程
        1.Go func() {}()
        2.Fun := func () {}
          go fun()
    ii.通讯:
        1.Chan := make(chan string[, 管道长度(int)], )
            a)默认不设置管道长度为无缓冲的管道,管道中只存储一个值
            b)设置之后为有缓冲的管道
        2.管道数据的存取:
            a)Chan<- “value”
            b)Value := <-chan
    iii.sync实现等待协程执行结束
        1.Var wg sync.WaitGrou
        2.Wg.Add(1):添加一个任务,在内部自增1
        3.wg.Done():结束任务,在wg内部减一
        4.Wg.Wait():检测wg中的计数器值是否为0,为0则继续执行,否则阻塞等待
d)应用场景:
    i.网络请求
    ii.本地文件I/O, 日志处理
    iii.通常用协程来实现异步的操作


相关文章
|
2月前
|
存储 安全 Java
并发编程篇
并发编程篇
|
3月前
|
算法 Java Go
并发编程(一)
并发编程(一)
|
3月前
|
安全 Java 数据库连接
并发编程(二)
并发编程(二)
|
3月前
|
Java 调度
并发编程(三)
并发编程(三)
|
缓存 安全
并发编程学习一
并发编程学习一
80 0
|
Java 编译器 程序员
高并发编程-happens-before
高并发编程-happens-before
94 0
|
Ubuntu 大数据 编译器
C++并发编程(上)
C++并发编程
270 0
C++并发编程(上)
|
前端开发 C++
C++并发编程(下)
C++并发编程(下)
169 0
C++并发编程(下)
|
Java 调度 数据库
JUC并发编程——多线程入门
JUC并发编程——多线程入门
145 0
JUC并发编程——多线程入门
|
缓存 监控 安全
聊聊并发编程的10个坑
聊聊并发编程的10个坑
聊聊并发编程的10个坑