进程,线程,协程

1.进程

  • 进程

    • 进程是资源分配的最小单位( 内存、cpu、网络、io)

    • 一个运行起来的程序就是一个进程

      • 什么是程序(程序是我们存储在硬盘里的代码)
      • 硬盘(256G)、内存条(8G)
      • 当我们双击图标,打开程序的时候,实际上就是通过I/O操作(读写)内存条里面
      • 内存条就是我们所指的资源
      • CPU分时
        • CPU比你的手速快多了,分时处理每个线程,但是由于太快然你觉得每个线程都是独占cpu
        • cpu是计算,只有时间片到了,获取cpu,线程真正执行
        • 当你想使用 网络、磁盘等资源的时候,需要cpu的调度
    • 进程具有独立的内存空间,所以没有办法相互通信

      • 进程如何通信
        • 进程queue
        • pipe
        • managers
        • RabbitMQ、redis等
    • 为什么需要进程池

      • 一次性开启指定数量的进程
      • 如果有十个进程,有一百个任务,一次可以处理多少个(一次性只能处理十个)
      • 防止进程开启数量过多导致服务器压力过大
from multiprocessing import Pool
import os, time


def worker(i):
    print('第%d次打印,我爱你中国'%(i))
    time.sleep(1)


if __name__ == '__main__':
    po = Pool(20)  # 定义一个进程池,最大进程数20
    for i in range(1,101):
        # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
        # 每次循环将会用空闲出来的子进程去调用目标
        po.apply_async(worker, args = (i,))

    print("----start----",end='\n')
    po.close()  # 关闭进程池,关闭后po不再接收新的请求

    po.join()  # 等待po中所有子进程执行完成,必须放在close语句之后
    print("-----end-----")
创建进程
    1、导包  import multiprocessing
    2、创建任务    函数
    3、用multiprocessing.Process(target=函数名)
    4、开启进程  start()
    5、join()
    6、terminate()   立即结束子进程
import os
from multiprocessing import Process
import time
num = 100
def func1():
    global num
    num +=50
    print(num,'进程号',os.getpid())


def func2():
    global num
    num += 500
    print(num,'进程号',os.getpid())


if __name__ == '__main__':
    print('kaishi')
    print(num)

    p1 = Process(target=func1)
    p2 = Process(target=func2)

    p1.start()

    p2.start()
    # p1.terminate()  
    # p2.terminate()
    p1.join()
    p2.join()
    print('结束')

2.线程

  • 有了进程为什么还需要线程
    • 因为进程不能同一时间只能做一个事情
  • 什么是线程
    • 线程是操作系统调度的最小单位
    • 线程是进程正真的执行者,是一些指令的集合(进程资源的拥有者)
    • 同一个进程下的读多个线程共享内存空间,数据直接访问(数据共享)
    • 为了保证数据安全,必须使用线程锁
  • GIL全局解释器锁
    • 在python全局解释器下,保证同一时间只有一个线程运行
    • 防止多个线程都修改数据
  • 线程锁(互斥锁)
    • GIL锁只能保证同一时间只能有一个线程对某个资源操作,但当上一个线程还未执行完毕时可能就会释放GIL,其他线程就可以操作了
    • 线程锁本质把线程中的数据加了一把互斥锁
      • mysql中共享锁 & 互斥锁
        • mysql共享锁:共享锁,所有线程都能读,而不能写
        • mysql排它锁:排它,任何线程读取这个这个数据的权利都没有
      • 加上线程锁之后所有其他线程,读都不能读这个数据
    • 有了GIL全局解释器锁为什么还需要线程锁
      • 因为cpu是分时使用的
  • 死锁定义
    • 两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去
from threading  import Thread
def func1(man):
    print('我是',man)

def func2(name):
    print('我是',name)
if __name__ == '__main__':
    print('主线程开始')
    t1 = Thread(target=func1,args=('aa1',))
    t2 = Thread(target=func2,kwargs={'name':'aa'})
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print('主线程结束')
def func():
    print('子线程开始')
    for i in range(5):
        print('线程',i)
        time.sleep(0.1)
        print('子线%s程结束'%i)
if __name__ == '__main__':
    print('主线程开始')
    t =Thread(target=func,daemon=True)
    # t = Thread(target=func)
    t.setDaemon(True)

    t.start()

    t.join()
    print('主线程结束')

from threading import Thread
import threading
num = 0
lock1 = threading.Lock()        #创建全局互斥锁

def func1():
    lock1.acquire()  # 上锁
    global num                      #修改全局变量
    for i in range(1000000):
        num +=1
    print('sum1',num)
    lock1.release()             #解锁

def func2():
    lock1.acquire()  # 上锁
    global num                      #修改全局变量
    for i in range(1000000):
        num +=1
    print('sum2',num)
    lock1.release()             #解锁
if __name__ == '__main__':




    t1 = Thread(target=func1)
    t2 = Thread(target=func2)
    t1.start()
    t2.start()

3.协程

  • 什么是协程
    • 协程微线程,纤程,本质是一个单线程
    • 协程能在单线程处理高并发
      • 线程遇到I/O操作会等待、阻塞,协程遇到I/O会自动切换(剩下的只有CPU操作)
      • 线程的状态保存在CPU的寄存器和栈里而协程拥有自己的空间,所以无需上下文切换的开销,所以快、
    • 为甚么协程能够遇到I/O自动切换
      • 协程有一个gevent模块(封装了greenlet模块),遇到I/O自动切换
  • 协程缺点
    • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上
    • 线程阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
'''
协程
实现协程的方式
1、yield
2、greenlet
3、gevent


'''
import time

import greenlet
import gevent
import urllib.request
from gevent import monkey


# 用yield 实现协程
# def work1():
#     while 1:
#         print('真可爱')
#         time.sleep(1)
#         yield
# def work2():
#     while 1:
#         print('真坏')
#         time.sleep(1)
#         yield
#
# g1 = work1()
# g2 = work2()
# while 1:
#     next(g1)
#     next(g2)


# def consumer():  # consumer 消费者
#     r = ''
#     while True:
#         n = yield r
#         print('[消费者] Consuming %s...' % n)
#
#
# def produce(c):  # produce 生产者
#     c.send(None)
#     for n in range(1, 6):
#         print('[生产者] Producing %s...' % n)
#         r = c.send(n)
#     c.close()
#
#
# c = consumer()
# produce(c)

#-----用greenlet实现协程
# def work1():
#     for i in range(5):
#         print('姬小飞2000秒')
#         time.sleep(0.2)
#         g2.switch()
#
#
# def work2():
#     for i in range(5):
#         print('波老师')
#         time.sleep(0.2)
#         g1.switch()
#
#
# g1 = greenlet.greenlet(work1)
# g2 = greenlet.greenlet(work2)
# g1.switch()  # 开启并切换到work1

# import gevent
#
#
# def jxf():
#     print('姬小飞开始')
#     gevent.sleep(4)
#     print('姬小飞结束')
#
#
# def jhc():
#     print('姬宏辰开始')
#     gevent.sleep(1)
#     print('姬宏辰结束')
#
#
# def lza():
#     print('刘再昂开始')
#     gevent.sleep(7)
#     print('刘再昂结束')
#
#
# gevent.joinall([
#     gevent.spawn(jxf),
#     gevent.spawn(jhc),
#     gevent.spawn(lza)
# ])```

你可能感兴趣的:(python,python基础,python)