线程、进程、协程/微线程

  • 并发的方式

并发处理是同一时间段内有几个程序都在一个cpu中处于运行状态,但任一时刻只有一个程序在cpu上运行。

多进程、多线程、IO多路复用(通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。如select、poll、epoll)

  • 进程

        资源分配的基本单位,

        Linux系统函数fork()可在父进程中创建一个子进程,在父进程接到新请求时,复制出一个子进程来处理,即父进程监控请求,子进程处理,实现并发处理。注意:必须是Linux系统,windows不能用fork。

  • 进程的几种状态

(1)run(运行状态):正在运行的进程或在等待队列中等待的进程,等待的进程只要以得到cpu就可以运行

(2)Sleep(可中断休眠状态):相当于阻塞或在等待的状态

(3)D(不可中断休眠状态):在磁盘上的进程

(4)T(停止状态):这中状态无法直观的看见,因为是进程停止后就释放了资源,所以不会留在linux中

(5)Z(僵尸状态):子进程先与父进程结束,但父进程没有调用wait或waitpid来回收子进程的资源,所以子进程就成了僵尸进程,如果父进程结束后任然没有回收子进程的资源,那么1号进程将回收

  • 线程

      CPU调度和分配的基本单位,程序执行的最小单位。

       在同一时间片只能有一个线程针对一个cpu执行指令,而且其他的线程必须被挂起。然后内核调度程序不断的唤醒/挂起线程来模拟多个任务的执行。

      一个进程可以由很多个线程组成,线程间共享进程的所有资源。线程有自己的堆栈、局部变量。

      线程的创建调用pthread_create

      线程中执行时一般都要进行同步和互斥,保证数据的一致性,因为他们共享同一进程的所有资源。

      同步:防止竞争(因同时修改导致数据的不一致)

      互斥:使用互斥锁防止多个线程同时读写某一块内存区域。互斥锁止允许一个线程进入临界区。

      信号量:内存区域只允许固定个数的线程进入,就要使用信号量,防止线程之间产生冲突。信号量许多个线程同时进入临界区。

 

  •  多线程的死锁

  定义:是指由于两个或者多个线程互相持有对方所需要的资源,相互等待资源,处于僵持状态

  处理办法:剥夺资源,或杀死其中一个线程

  • 多进程与多线程的区别与联系

(1)单位:进程是资源分配的最小单位,线程是程序执行/CPU调度的最小单位。

(2)地址空间:进程有独立地址空间(用于建立数据表来维护代码段、堆栈段和数据段);线程使用相同的地址空间(共享进程中的数据)

(3)开销:CPU切换线程及创建线程的开销比进程小(不需要开辟新的地址空间)进程间切换代价大,线程间切换代价小

(4)通信:同一进程间的线程间由于共享进程的数据,通信更方便,难点在于处理同步与互斥;而进程间的通信需要以IPC(进程间通信InterProcess Communication,如管道、消息队列、信号量、共享内存)的方式进行通信

(5)健壮性:多进程程序更加健壮(多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。)

(6)结束的影响:进程的结束会将它所拥有的所有线程销毁,线程的销毁不影响同个进程下的线程

(7)私有属性:“线程有自己的私有属性TCB,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志”

 

  • 协程、微线程

       协程,又称微线程,纤程,coroutine 。

       协程是一个线程执行,两个子过通过相互作完成某个任务。协程和子程序调用很像,但协程是在子程序内部中断去执行别的子程序,适当时候返回接着执行,中断有别于函数调用。

    举个例子(协程的运作):

  

  • 协程与多线程的区别

(1)开销。协程执行效率高,协程是单个线程执行,以子程序中断的形式切换,没有多线程切换的开销。

(2)协程不需要多线程的锁机制。不存在同时写变量冲突。

  • 使用   yield+协程  实现生产者-消费者模型

       传统的生产者-消费者模型是一个线程写消息,一个线程取消息,使用锁机制可能死锁。如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产。

     yield一般配合send()方法使用:

send(value)将value值传递给yield表达式——下一次yield时返回值给send处——send——yield——。。。

程序:

def consumer():#消费者
    r = ''#r初始为空字符,启动生成器后变成'200 0K'
    while True:
        n = yield r#接收send的value作为n,下一次运行时返回r给produce中的r
        if not n:#没有生产时不能消费
            return
        print('[CONSUMER]Consuming %s...' % n)
        r = '200 OK'

def producer(c):#生产者
    c.send(None)#启动生成器,启动时必须value为None
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER]Producing %s...' % n)
        r = c.send(n)#send将value传递给yield表达式的值,返回下一次运行yield时的值
        print('[PRODUCER]Consumer return: %s' % r)
    c.close()#生产完5个就结束

c = consumer()
producer(c)

运行结果:

[PRODUCER]Producing 1...
[CONSUMER]Consuming 1...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 2...
[CONSUMER]Consuming 2...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 3...
[CONSUMER]Consuming 3...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 4...
[CONSUMER]Consuming 4...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 5...
[CONSUMER]Consuming 5...
[PRODUCER]Consumer return: 200 OK

运行过程:

运行分析:

step1:produce(c),运行produce,运行到c.send(None)——运行c即consumer(),启动生成器,value=None,不需要把value给什么yield接收

step2:运行consumer()时运行遇到n=yield r,返回r=''作为n,切换回producer中的原send处

step3:producer中首轮生产者生产n=1,遇到r=c.send(n),将value=n传给yield所在表达式作为n,此时n=1,消费者消费n=1

step4:在consumer()的while True循环,下一次运行yield所在表达式,返回此时的r=‘200 OK’给r

step5:在producer()中进行while的循环,n+1后变成2,进行:“send 切换到yield 再次yield 切换回send”的循环

step6:循环直到n=5,不再进入while,执行c.close()结束

  注意:

1.第一次启动生成器c.send(None),value值为None,启动生成器时,调用c函数,不是到某个yield

2.send传值是传给了表达式,和yield后面是什么没有关系,再次遇到yield切换回原来send处。注意切换的位置以及传回的是yield后面的值

3.传回send是要把send的赋值表达式运行一次的,不是从send语句下面开始。

 

 

参考网址:

https://blog.csdn.net/zhou753099943/article/details/51771220

https://www.cnblogs.com/zhehan54/p/6130030.html

https://www.nowcoder.com/questionTerminal/234895a70e0b40e19db7f3fbaabc5fa3

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000

https://blog.csdn.net/sunflowerduidui/article/details/51820067

https://www.cnblogs.com/zhang-can/p/7215506.html   这个链接讲得比较深入,涉及到锁/创建新线程/通信等等的程序,有需要可参考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章