其他分享
首页 > 其他分享> > day31总结

day31总结

作者:互联网

目录

回顾

1.GIL全局解释器锁
1.本质上是一把互斥锁.
2.Cpython才有的
3.在同一个进程下开启多个线程,让并发变成串行,保证线程安全.

2.何时使用多线程或多进程:
- IO密集型:
使用多线程

3.死锁现象
A,B两把锁,相互调用对方,导致出现死锁现象.

4.递归锁:
解决死锁问题.
普通锁:
只能被一个线程去引用.

递归锁:
可以被多个线程去引用.
当递归锁的引用计数为0才会释放,让其他任务去抢.

5.信号量
互斥锁:
一次只能被一个线程去使用.
信号量(本质上是一把锁):
一次可以被多个线程去使用.

6.线程队列:
- FIFO: 先进先出
- LIFO: 后进先出
- 优先级队列: 根据数字的大小进行判断优先级, 数字越小优先级越高.

7.TCP服务端实现并发
- 服务端:
- 让连接客户端由串行变成并发

Event事件

Event事件的作用:
- 用来控制线程的执行.
- 由一些线程去控制另一些线程.

from threading import Event
from threading import Thread
import time
# 调用Event类实例化一个对象
e = Event()

# 若该方法出现在任务中,则为False,阻塞
# e.wait()  # False

# 若该方法出现在任务中,则将其他线程的Flase改为True,进入就绪态与运行态
# e.set()  # True


def light():
    print('红灯亮...')
    time.sleep(5)
    # 应该开始发送信号,告诉其他线程准备执行
    e.set()  # 将car中的False ---> True
    print('绿灯亮...')


def car(name):
    print('正在等红灯....')
    # 让所有汽车任务进入阻塞态
    e.wait()  # False
    print(f'{name}正在加速漂移....')


# 让一个light线程任务 控制多个car线程任务
t = Thread(target=light)
t.start()

for line in range(10):
    t = Thread(target=car, args=(f'童子军jason{line}号', ))
    t.start()

线程池与进程池

1)什么是进程池与线程池?
进程池与线程池是用来控制当前程序允许创建(进程/线程)的数量.

2)进程池与线程池的作用:
保证在硬件允许的范围内创建 (进程/线程) 的数量.

3)如何使用:

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time

# ProcessPoolExecutor(5)  # 5代表只能开启5个进程
# ProcessPoolExecutor()  # 默认以CPU的个数限制进程数

pool = ThreadPoolExecutor(5)  # 5代表只能开启5个线程 -5 +1 -1 +1 -1
# ThreadPoolExecutor()  # 默认以CPU个数 * 5 限制线程数

# t = Tread()  # 异步提交
# t.start(0)



# pool.submit('传函数地址')  # 异步提交任务
# def task():
#     print('线程任务开始了...')
#     time.sleep(1)
#     print('线程任务结束了...')
#
#
# for line in range(5):
#     pool.submit(task)


# 异步提交任务
# pool.submit('传函数地址').add_done_callback('回调函数地址')
def task(res):
    # res == 1
    print('线程任务开始了...')
    time.sleep(1)
    print('线程任务结束了...')
    return 123


# 回调函数
def call_back(res):
    print(type(res))
    # 注意: 赋值操作不要与接收的res同名
    res2 = res.result()
    print(res2)


for line in range(5):
    pool.submit(task, 1).add_done_callback(call_back)


# 会让所有线程池的任务结束后,才往下执行代码
# pool.shutdown()

print('hello')

协程

# # # 串行执行
# # import time
# #
# #
# # def func1():
# #     for i in range(10000000):
# #         i+1
# #
# #
# # def func2():
# #     for i in range(10000000):
# #         i+1
# #
# #
# # start = time.time()
# # func1()
# # func2()
# # stop = time.time()
# # print(stop - start)  # 0.8930509090423584


# 验证计算密集型的情况下效率更低: # 1.4250171184539795
# 基于yield并发执行
# import time
#
#
# def func1():
#     while True:
#         10000000+1
#         yield
#
#
# def func2():
#     # g生成器对象
#     g = func1()
#     for i in range(10000000):
#         time.sleep(100)  # 模拟IO,yield并不会捕捉到并自动切换
#         i+1
#         next(g)
#
#
# start = time.time()
# func2()
# stop = time.time()
# print(stop-start)


'''gevent:
    是一个第三方模块,可以帮你监听IO操作, 并切换.

- 使用gevent目的:
    为了实现单线程下,实现遇到IO, 保存状态 + 切换

pip3 install gevent
'''
from gevent import monkey
monkey.patch_all()  # 可以监听该程序下所有的IO操作
import time
from gevent import spawn, joinall  # 用于做切换 + 保存状态


def func1():
    print('1')
    # IO操作
    time.sleep(1)


def func2():
    print('2')
    time.sleep(3)


def func3():
    print('3')
    time.sleep(5)


start_time = time.time()

s1 = spawn(func1)
s2 = spawn(func2)
s3 = spawn(func3)

# s2.join()  # 发送信号,相当于等待自己 (在单线程的情况下)
# s1.join()
# s3.join()
# 必须传序列类型
joinall([s1, s2, s3])

end_time = time.time()

print(end_time - start_time)

标签:总结,day31,线程,IO,time,print,import,def
来源: https://www.cnblogs.com/zhm-cyt/p/11734048.html