线程

36 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

互斥锁

进程与进程之间的数据是不共享 , 可以使用文件共享数据实现进行之间的通信。当数据共享就会有竞争,竞争带来的问题就是数据错乱。

from multiprocessing import Process
import time
import json

def search(name):
    time.sleep(1)
    dic = json.load(open('db.txt' , 'r' , encoding='utf-8'))
    print(f'{name}正在查看票源 , 当前剩余票数为{dic["count"]}')

def get(name):
    dic = json.load(open('db.txt', 'r', encoding='utf-8'))
    if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(2)
        json.dump(dic , open('db.txt', 'w', encoding='utf-8'))
        print(f'{name}购票成功')

def func(name):
    search(name)
    get(name)

if __name__ == '__main__':
    for i in range(1 , 6):
        p = Process(target=func , args=(f'Tom{i}号',))
        p.start()

互斥锁:就是多个进程在访问同一个资源,加上互斥锁把并发成串行,可以保证数据的安全不会错乱;但是效率比较低。

加锁处理:以牺牲效率的情况 ,来保证数据的安全

from multiprocessing import Process , Lock
import time
import json

def search(name):
    time.sleep(1)
    dic = json.load(open('db.txt' , 'r' , encoding='utf-8'))
    print(f'{name}正在查看票源 , 当前剩余票数为{dic["count"]}')

def get(name):
    dic = json.load(open('db.txt', 'r', encoding='utf-8'))
    if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(2)
        json.dump(dic , open('db.txt', 'w', encoding='utf-8'))
        print(f'{name}购票成功')
    else:
        print(f'{name}购票不成功')

def func(name , l):
    search(name)
    # 加锁
    l.acquire()
    get(name)
    # 解锁
    l.release()

if __name__ == '__main__':
    # 创建锁
    l = Lock()
    for i in range(1 , 6):
        p = Process(target=func , args=(f'Tom{i}号',l))
        p.start()
from multiprocessing import Process , Lock
import time
import json

def search(name):
    time.sleep(1)
    dic = json.load(open('db.txt' , 'r' , encoding='utf-8'))
    print(f'{name}正在查看票源 , 当前剩余票数为{dic["count"]}')

def get(name):
    dic = json.load(open('db.txt', 'r', encoding='utf-8'))
    if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(2)
        json.dump(dic , open('db.txt', 'w', encoding='utf-8'))
        print(f'{name}购票成功')
    else:
        print(f'{name}购票不成功')

def func(name , l):
    search(name)
    # 加锁
    l.acquire()
    get(name)
    # 解锁
    l.release()

if __name__ == '__main__':
    # 创建锁
    l = Lock()
    for i in range(1 , 6):
        p = Process(target=func , args=(f'Tom{i}号',l))
        p.start()
        p.join()

信号量

信号量也是一把锁

互斥锁是同一时间是只有一个任务能抢到锁

信号量同一时间可以有多个任务拿到锁

from multiprocessing import Process , Semaphore
import time


def black_room(name,s):
    s.acquire()
    print(f'{name}猥琐的溜进小黑屋')
    time.sleep(3)
    print(f'{name}惊恐的跑出房间')
    s.release()

if __name__ == '__main__':
    # 设置信号量 , 设置有多少个锁
    s = Semaphore(3)
    for i in range(10):
        p = Process(target=black_room , args=(f'张三{i}号',s))
        p.start()

进程通信

进程通信:消息队列

消息队列的使用:在内存中建立队列模型 , 进程通过队列将消息存入 , 或者从队列取出完成进程通信

from multiprocessing import Queue , Process
import time

def write(q):
    # 将数据写入到queue消息队列中
    ls = ['武则天','孙悟空','李白','孙尚香','亚瑟','鲁班']
    for i in ls:
        q.put(i)
        print(f'queue获取到值:{i}')
        time.sleep(2)

def read(q):
    # 从消息队列中获取数据
    while True:
        # 判断消息队列总消息是否为空
        if not q.empty():
            value = q.get(True)
            print(f'从消息队列中获取到值:{value}')
            time.sleep(3)
        else:
            break


if __name__ == '__main__':
    q = Queue()
    w = Process(target=write,args=(q , ))
    r = Process(target=read , args=(q,))
    w.start()
    w.join()
    r.start()
    r.join()
    print('数据读取完毕')

线程

线程是资源分配单位,每一个进程中至少都会有一个线程,这个线程默认为主线程。

每个程序启动都默认有一个主线程 ,其他都是个我们自己创建的子线程

from threading import Thread

def work(name):
    print(f'{name}在种田')

if __name__ == '__main__':
    t = Thread(target=work , args=('阿宸',))
    t.start()

在多个线程中 , 线程之间的数据是共享的

from threading import Thread

age = 20

def work(name):
    global age
    age = 24
    print(f'{name}高龄{age} , 还在种田')

if __name__ == '__main__':
    t = Thread(target=work , args=('阿宸',))
    t.start()
    print(age)

进程类

from multiprocessing import Process
import time

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

    def eat(self , name):
        for i in range(5):
            print(f'{name}在吃第{i}碗鸡汤')
            time.sleep(1)

    # 自定义的进程类中 , 所有的任务需要到run方法中调用
    def run(self):
        print('开启进程任务')
        self.eat(self.name)
        print('结束进程任务')

if __name__ == '__main__':
    p = MyProcess('阿宸')
    p.start()

线程类

from threading import Thread

class MyThread(Thread):

    def __init__(self):
        super().__init__()

    def read(self):
        for i in range(5):
            print('感谢大家收看 , 感谢大家收听 , 讲的不好请大家见谅')
            print('各位身体倍棒')
            print('各位晚安 , 好梦')

    def run(self):
        self.read()

if __name__ == '__main__':
    t = MyThread()
    t.start()