线程、进程与协程

线程、进程与协程

python程序的运行逻辑是,在.py文件从上往下,从左往右加载代码,有python解释器翻译成CPU可读程序后,交给操作系统OS,由操作系统调度CPU执行。

那什么是线程?

线程是操作系统能够进行运算调度的最小单位。它包含在进程中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程执行不同任务

那什么是进程?

执行的一个程序就是一个进程。进程是对线程的资源整合,线程间资源是共有的,但进程间资源是对立的。

什么是协程?

协程,又称微线程,纤程。协程是用户态的轻量级线程
协程本质上就是一个单线程
协程拥有自己的寄存器和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来时,恢复先前保存的寄存器上下文和栈。即协程能保留上一次调用时的状态,过程重入时,进入上次离开时的逻辑流位置

协程优点:

无多线程间切换的开销
无需原子操作锁定及同步开销(各种线程锁)
方便切换控制流,简化编程模型
高并发+高扩展+低成本:一个CPU支持上万协程没有问题。所以适用高并发。

协程缺点:

无法利用CPU的多和资源。协程本身还是一个单线程。无法利用上CPU多核,但可以与进程配合运行
进行阻塞操作时,会阻塞整个程序

进程与线程的区别:

1、线程间资源是共享的,进程存在自己独立的资源
2、多线程数据共享
3、线程间可以通讯,进程不行
4、多进程的创建是完全复制的,消耗较大
5、改变主线程可以影响子线程,主进程不可以

进程与线程不存在快慢,进程与线程执行速度是一致的。

说到解释器,通用的Cpython解释器中存在GIL锁(Global Interpreter lock):在同一时刻,只能有一个线程进入解释器;
造成的影响是:无法调用多核cpu,造成只能调用一个cpu的现象。
故!理论上,python并没有绝对意义上的多线程。
后期使用多进程的方式,使任务并发处理,但此方式并不全面,因为,线程间是可以相互通讯的,资源是共享的,但是进程是不可以的。

  • 线程使用:import threading
#!-*- coding:utf-8 -*-
#date: 2020/4/21

import threading
import time

def foo(n):
    print(threading.active_count()) 
    # [<_MainThread(MainThread, started 26644)>, <Thread(Thread-1, started 12656)>]
	# [<_MainThread(MainThread, started 26644)>, <Thread(Thread-1, started 12656)>, <Thread(Thread-2, started 26116)>]
    print(n)
    time.sleep(2)

t1 = threading.Thread(target=foo,args=('第一个线程',)) # 创建进程1
t2 = threading.Thread(target=foo,args=('第一个线程',)) # 创建进程2

t = []
t.append(t1)
t.append(t2)

if __name__ == '__main__':
	print(threading.active_count()) # [<_MainThread(MainThread, started 26644)>]
    for i in t:
        i.start() # 运行进程
    i.join() # 阻塞 当进程2结束才继续执行主进程

    print('线程结束')

第二种创建方式,类方式创建:

#!-*- coding:utf-8 -*-
#date: 2020/4/21

import threading
import time

class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        print('hello',self.name)
        time.sleep(2)

if __name__ == '__main__':
    pro_list = []
    for i in range(2):
        i = MyThread()
        pro_list.append(i)
    for p in pro_list:
        p.start()
    p.join()
    print('线程结束')

# 运行结果:
'''
hello Thread-1
hello Thread-2
线程结束
'''

结论:
在python中:
如果任务是IO密集型的,可以使用多线程;
如果是计算密集型的,改用C处理。

线程同步锁:

x = threading.Lock()

x.acquire()
x.release()
包住

上面在重复使用的过程中,如果锁建立过多,容易造成死锁现象,故引出递归锁(本质是,使用了一个计数器,每增加一次,加1,释放一次,减1):

lock = threading.RLock()
使用方式一致:
lock.acquire()
lock.release()
包住。

  • 进程使用:from multiprocessing import Process
    进程的使用与线程时完全一致的。
    正常创建:
#!-*- coding:utf-8 -*-
#date: 2020/4/21

from multiprocessing import Process
import time

def foo(n):
    print(n)
    time.sleep(2)

t1 = Process(target=foo,args=('第一个进程',))
t2 = Process(target=foo,args=('第一个进程',))
t = []
t.append(t1)
t.append(t2)

if __name__ == '__main__':
    for i in t:
        i.start()
    i.join()
    print('进程结束')

类式创建:

from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()

    def run(self):
        print('hello',self.name)
        time.sleep(2)

if __name__ == '__main__':
    pro_list = []
    for i in range(2):
        i = MyProcess()
        pro_list.append(i)
    for p in pro_list:
        p.start()
    p.join()
    print('进程结束')
    
# 运行结果:
'''
hello Process-1
hello Process-2
进程结束
'''

进程之间是无法进行数据交互共享的,注意:可以通过queue队列或pipes管道的方式进行数据共享。
简单举例,仅供参考:

from multiprocessing import Process,Queue
import time

class MyProcess(Process):
    def __init__(self,q):
        self.queue = q
        super(MyProcess, self).__init__()

    def run(self):
        print('hello',self.name)
        self.queue.put(self.name)
        time.sleep(2)

if __name__ == '__main__':
    q = Queue()
    pro_list = []
    for i in range(2):
        i = MyProcess(q)
        pro_list.append(i)
    for p in pro_list:
        p.start()

    print('队列获取数据',q.get())
    print('队列获取数据',q.get())

    print('进程结束')
# 运行结果
'''
hello MyProcess-1
队列获取数据 MyProcess-1
hello MyProcess-2
队列获取数据 MyProcess-2
进程结束
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值