文章目录
一、GIL与普通互斥锁区别
from threading import Thread
money = 100
def fask():
    global money
    money -= 1
for i in range(100):
    t = Thread(target=fask)
    t.start()
print(money) # 0
 
通过上面的操作验证了GIL全局解释器锁是存在的
from threading import Thread, Lock
import time
money = 100
mutex = Lock()
def fask():
    global money
    mutex.acquire()
    num = money
    time.sleep(0.1)
    money = num - 1
    mutex.release()
t_list = []
for i in range(100):
    t = Thread(target=fask)
    t.start()
    t_list.append(t)
for i in t_list:
    i.join()
print(money) # 0
 
二、死锁现象
当多个线程同时需要某一个锁的资源时,无法获取锁的资源会等待获取,多个线程都互相等待对方锁的资源,就会产生死锁现象。
def play(num):
    mutexA.acquire()
    print("子进程%d获取A锁"%num)
    time.sleep(3)
    mutexB.acquire()
    print("子进程%d获取B锁"%num)
    mutexB.release()
    print("子进程%d释放B锁"%num)
    mutexA.release()
    print("子进程%d释放A锁" % num)
def play1(num):
    mutexB.acquire()
    print("子进程%d获取B锁"%num)
    time.sleep(3)
    mutexA.acquire()
    print("子进程%d获取A锁" % num)
    mutexA.release()
    print("子进程%d释放A锁"%num)
    mutexB.release()
    print("子进程%d释放B锁"%num)
t = Thread(target=play, args=(1, ))
t1 = Thread(target=play1, args=(2, ))
t.start()
t1.start()
 

三、信号量
信号量在不同的知识体系中 展示出来的功能是不一样的
 在互斥锁中展现为多个可以被多个资源获取的互斥锁
from threading import Thread, Semaphore
import time
import random
sp = Semaphore(3)
def fask(num):
    sp.acquire()
    print("%d号子弹飞出"%num)
    time.sleep(random.randint(1, 2))
    sp.release()
    print("%d子弹命中"%num)
for i in range(20):
    t = Thread(target=fask, args=(i, ))
    t.start()
 

四、event事件
一般情况下子线程的运作是与主线程有关的,但使用了event后可以让子线程决定子线程的运行状况
from threading import Thread, Event
import time
eventO = Event()
def wait_time():
    print("三秒后即将开始抢玻璃")
    time.sleep(3)
    print("三秒到开始抢玻璃")
    eventO.set()
def get_glass(num):
    print("%d号选手正在参与抢玻璃!"%num)
    eventO.wait()
    print("%d号选手抢到了玻璃!"%num)
t = Thread(target=wait_time)
t.start()
for i in range(1, 31):
    t1 = Thread(target=get_glass, args=(i, ))
    t1.start()
 
五、进程池
from concurrent.futures import ProcessPoolExecutor
import time
def make_pool(num):
    print("%d号子进程正在被处理"%num)
    start_time = time.strftime("%Y %m %d %X")
    print(f"开始时间{start_time}")
    time.sleep(1)
def func(*args, **kwargs):
    args[0].result()
if __name__ == '__main__':
    pool = ProcessPoolExecutor(2)
    for i in range(1, 11):
        pool.submit(make_pool, i).add_done_callback(func)
 

六、线程池
from concurrent.futures import ThreadPoolExecutor
import time
def make_pool(num):
    print("%d号子线程正在被处理"%num)
    start_time = time.strftime("%Y %m %d %X")
    print(f"开始时间{start_time}")
    time.sleep(1)
def func(*args, **kwargs):
    args[0].result()
pool = ThreadPoolExecutor(2)
for i in range(1, 11):
    pool.submit(make_pool, i).add_done_callback(func)
 

七、协程
协程的主要目的是在单线程下完成并发,其本质是在于不断切换状态,在多个需要资源的代码之间来回服务。协程就是自己通过代码来检测程序的IO操作并自己处理 让CPU感觉不到IO的存在从而最大幅度的占用CPU。
from gevent import monkey;monkey.patch_all()  # 固定编写 用于检测所有的IO操作
from gevent import spawn
import time
def play(name):
    print('%s play 1' % name)
    time.sleep(5)
    print('%s play 2' % name)
def eat(name):
    print('%s eat 1' % name)
    time.sleep(3)
    print('%s eat 2' % name)
start_time = time.time()
g1 = spawn(play, 'jason')
g2 = spawn(eat, 'jason')
g1.join()  # 等待检测任务执行完毕
g2.join()  # 等待检测任务执行完毕
print('总耗时:', time.time() - start_time)
 
协程完成服务器与客户端的信息交互
服务器
from gevent import monkey;monkey.patch_all()
from gevent import spawn
import socket
def create_server():
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    while True:
        sock, addr = server.accept()
        spawn(communication, sock, addr)
def communication(sock, addr):
    while True:
        data = sock.recv(1024)
        print(f"{addr}客户端:{data.decode('utf8')}")
        sock.send("服务器收到消息".encode("utf8"))
spawn(create_server).join()
 
客户端
import socket
client = socket.socket()
client.connect(("127.0.0.1", 8080))
while True:
    client.send("协程信息测试".encode("utf8"))
    data = client.recv(1024)
    print(f"服务器:{data.decode('utf8')}")











