并发编程--线程

GIL全局解释器锁

  1. GIL:全局解释器锁

翻译:在同一个进程下开启的多线程,同一时刻只能一个线程执行,因为Cpython的内存管理不是线程安全。

GIL全局解释器锁,本质上就是一把互斥锁,保证数据安全。

定义:在Cpython解释器中,同一个进程下开启多线程,同一时刻只能一个线程执行,无法利用多核优势。

  1. GIL全局解释器锁的优缺点:

    优点:保证数据的安全

    缺点:单个线程下,开启多个线程,牺牲执行效率,无法实现并行,只能实现串行。

    —IO密集型下使用多线程

    —计算密集型下使用多进程

import time
from threading import Thread

n = 100
def task():
    global n
    m = n
    time.sleep(3)
    n = m - 1

if __name__ == '__main__':
    list1 = []
    for line in range(10):
        t = Thread(target=task)
        t.start()
        list1.append(t)

    for t in list1:
        t.join()

    print(n)

多线程

IO密集型下使用多线程

计算密集型下使用多进程

  1. IO密集型任务,每个任务4S
  • 单核:开启线程比进程节省资源.
  • 多核:
    • 多线程:开启4哥子线程:16S
    • 多进程:开启4哥进程:16S + 申请开启资源消耗的时间
# 计算密集型任务
def task1():
    # 计算1000000次 += 1
    i = 10
    for line in range(10000000):
        i += 1

# IO密集型任务
def task2():
    time.sleep(3)

if __name__ == '__main__':
    # 1、测试多进程:
    # 测试计算密集型
    # start_time = time.time()
    # list1 = []
    # for line in range(6):
    #     p = Process(target=task1)
    #     p.start()
    #     list1.append(p)
    #
    # for p in list1:
    #     p.join()
    # end_time = time.time()
    # # 消耗时间: 0.44082188606262207
    # print(f'计算密集型消耗时间: {end_time - start_time}')
    #
    # # 测试IO密集型
    # start_time = time.time()
    # list1 = []
    # for line in range(6):
    #     p = Process(target=task2)
    #     p.start()
    #     list1.append(p)
    #
    # for p in list1:
    #     p.join()
    # end_time = time.time()
    # # 消耗时间: 0.44082188606262207
    # print(f'IO密集型消耗时间: {end_time - start_time}')
  1. 计算密集型,每个任务4S
  • 单核:开启线程比进程节省资源
  • 多核:
    • 多线程:开启4个子进程–>16S
    • 多进程:开启多个进程–>4s

计算密集型:多进程

​ 假设100份原材料同时到达工厂,聘请100个人同时制造,效率最高

IO密集型:多线程

假设100份原材料,只有40份了,其他还在路上,聘请40个人同时制造

# 测试计算密集型
    start_time = time.time()
    list1 = []
    for line in range(6):
        p = Thread(target=task1)
        p.start()
        list1.append(p)

    for p in list1:
        p.join()
    end_time = time.time()
    # 消耗时间: 0.44082188606262207
    print(f'计算密集型消耗时间: {end_time - start_time}')

    # 测试IO密集型
    start_time = time.time()
    list1 = []
    for line in range(6):
        p = Thread(target=task2)
        p.start()
        list1.append(p)

    for p in list1:
        p.join()
    end_time = time.time()
    # 消耗时间: 0.44082188606262207
    print(f'IO密集型消耗时间: {end_time - start_time}')

协程

进程:资源单位

线程:执行单位

协程:单线程下实现并发

  • 在IO密集型的情况下,使用协程能提高最高的效率.
  • 注意:协程不是任何单位,只是一个程序员YY出来的东西

总结:多进程-->多线程-->让每个线程都实现协程.(但线程下实现并发)

协程的目的:手动实现‘遇到IO切换+保存状态‘去骗操作系统,让操作系统误以为没有IO操作,将CPU的执行权限给你。

'''
# import time
# def task1():
#     time.sleep(1)
#
# def task2():
#     time.sleep(3)
#
# def task3():
#     time.sleep(5)
#
# def task4():
#     time.sleep(7)
#
# def task5():
#     time.sleep(10)


# 遇到IO切换(gevent模块) + 保存状态
# def func():
#     yield

from gevent import monkey  # 猴子补丁
monkey.patch_all()  # 监听所有的任务是否有IO操作
from gevent import spawn  # spawn(任务)
from gevent import joinall
import time

def task1():
    print('start from task1...')
    time.sleep(1)
    print('end from task1...')

def task2():
    print('start from task2...')
    time.sleep(3)
    print('end from task2...')

def task3():
    print('start from task3...')
    time.sleep(5)
    print('end from task3...')


if __name__ == '__main__':

    start_time = time.time()
    sp1 = spawn(task1)
    sp2 = spawn(task2)
    sp3 = spawn(task3)
    # sp1.start()
    # sp2.start()
    # sp3.start()
    # sp1.join()
    # sp2.join()
    # sp3.join()
    joinall([sp1, sp2, sp3])

    end_time = time.time()

    print(f'消耗时间: {end_time - start_time}')
posted @ 2019-12-09 21:14  Mr-Allen  阅读(99)  评论(0编辑  收藏  举报