Pyhton线程同步

Python线程间通信

在这里插入图片描述
1、线程锁

#! /usr/bin/evn python3
# --*-- coding: utf-8 --*--

from threading import Lock,RLock
import threading

#说明:
# 1、用锁会影响性能(必然存在的)
# 2、锁会引起死锁
# 死锁两种常见的情况:
# 1、lock.acquire()  lock.acquire()两次使用锁而无释放
# 2、资源竞争
'''A(a,b)
    acquire(a)
    acquire(b)
    B(a,b)
    acquire(a)
    acquire(b)
'''
# 3、两次调用lock.acquire()
# 解决办法:Python中引入了可重入的锁from threading import RLock
# 说明:在同一个线程里面,可以连续调用多次acquire(),一定要注意acquire()调用要和release()调用次数一致
'''
    def add():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        dosomething(lock)
        total += 1
        lock.release()
        
    def dosomething():
        lock.acquire()
        lock.release()

'''
#锁解决数据不一致问题

total = 0
lock = Lock()

def add():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total += 1
        lock.release()

def desc():
    global total
    global lock
    for j in range(1000000):
        lock.acquire()
        total  -= 1
        lock.release()

threading1 = threading.Thread(target = add)
threading2 = threading.Thread(target= desc)

threading1.start()
threading2.start()

threading1.join()
threading2.join()
print(total)


#解决可以多次使用acquire()问题

total = 0
lock = RLock()

def add():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        lock.acquire()
        total += 1
        lock.release()
        lock.release()

def desc():
    global total
    global lock
    for j in range(1000000):
        lock.acquire()
        total  -= 1
        lock.release()

threading1 = threading.Thread(target = add)
threading2 = threading.Thread(target= desc)

threading1.start()
threading2.start()

threading1.join()
threading2.join()
print(total)

2、线程条件变量

#! /usr/bin/evn python3
# --*-- coding: utf-8 --*--

#线程中的条件变量()
# 通知天猫与小爱之间的来回切换

import threading

class XiaoAi(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="小爱")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{}: 在".format(self.name))
        self.lock.release()

        self.lock.acquire()
        print("{} : 好啊!".format(self.name))
        self.lock.release()


class TianMao(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="天猫精灵")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{} : 小爱同学".format(self.name))
        self.lock.release()

        self.lock.acquire()
        print("{} : 我们来对古诗吧!".format(self.name))
        self.lock.release()


if __name__ == "__main__":
    lock = threading.Lock()
    xiaoai = XiaoAi(lock)
    tianmao = TianMao(lock)

    tianmao.start()
    xiaoai.start()


#wait() 等待某个条件变量的通知
#notify() 通知调用了wait()方法的启动
from threading import Condition

class XiaoAi(threading.Thread):
    def __init__(self,cond):
        super().__init__(name="小爱")
        self.cond = cond

    def run(self):
        with self.cond:
            self.cond.wait()
            print("{}: 在".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 好啊!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 君住长江尾!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 共饮长江水!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 此恨何时已!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 定不负相思意!".format(self.name))
            self.cond.notify()
            self.cond.wait()

class TianMao(threading.Thread):
    def __init__(self,cond):
        super().__init__(name="天猫精灵")
        self.cond = cond

    def run(self):
        with self.cond:#也可以这样调用:self.cond.acquire()方法,但一定要self.cond.release()方法
            print("{} : 小爱同学".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我们来对古诗吧!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我住长江头!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 日日思君不见君!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 此水几时休!".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 只愿君心似我心!".format(self.name))
            self.cond.notify()
            self.cond.wait()

if __name__ == "__main__":
    cond = threading.Condition()
    xiaoai = XiaoAi(cond)
    tianmao = TianMao(cond)

    #启动顺序很重要
    #我们先要一定调用Condition  with()方法,with就相当于调用
    #在调用with之后  cond之后才能调用wait()或者notify()方法
    #condition有两层锁,一把底层锁会在线程调用了wait方法的时候释放,上面的锁会在每次调用wait()的时候分配一把并放入condition等待队列中,等待notify()方法的唤醒。
    xiaoai.start()
    tianmao.start()

3、线程信号量

#! /usr/bin/evn python3
# --*-- coding: utf-8 --*--

#Semaphore是用于控制进入数量的锁
#文件, 读、写, 写一般只是用于一个线程写,读可以允许有多个

#简单的模拟一个爬虫

import threading
import time

class HtmlSpider(threading.Thread):
    def __init__(self,url,sem):
        super().__init__()
        self.url = url
        self.sem = sem

    def run(self):
        time.sleep(2)
        print("got html text success")
        self.sem.release()

class UrlProducer(threading.Thread):
    def __init__(self,sem):
        super().__init__()
        self.sem = sem

    def run(self):
        for i in range(20):
            self.sem.acquire()
            html_thread = HtmlSpider("https://baidu.com/{}".format(i),self.sem)
            html_thread.start()


if __name__ == "__main__":
    sem = threading.Semaphore(3)
    url_producer = UrlProducer(sem)
    url_producer.start()

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值