day 11 课堂笔记 线程

1. 线程join

回忆:进程join是让主进程阻塞等待,等待子进程执行完毕后,主进程再次执行。线程join同理

from threading import Thread, currentThread
import time


def task():
    print(f'{currentThread().getName()}开始了')
    time.sleep(2)
    print(f'{currentThread().getName()}结束了')
  

if __name__ == '__main__':
    t1 = Thread(target=task, name='线程1')
    t1.start()
    t1.join()
    print('=====主进程')

2. 线程锁

2.1 线程操作公共数据问题

from threading import Thread, currentThread
import time


x = 100


def task():
    global x
    print(1111)
    temp = x
    print(333)
    temp -= 1
    print(22222)
    x = temp
  

if __name__ == '__main__':
    t_list = []
    for i in range(100):
        t = Thread(target=task,)
        t.start()
        t_list.append(t)
        
    for i in t_list:
        i.join()
    print(f'======主线程{x}')

2.2 加锁处理

from threading import Thread, currentThread, Lock
import time
x = 100


def task(lock):
	global x
    print(1111)
    lock.acquire()
    temp = x
    print(22222)
    lock.release()
    x = temp
  

if __name__ == '__main__':
    lock = Lock()
    t_list = []
    for i in range(100):
        t = Thread(target=task, args=(lock,))
        t.start()
        t_list.append(t)
    for i in t_list:
        i.join()
    print(f'====主线程{x}')

小结:

  • 无论是进程还是线程加锁就是为了让锁住的程序变成串行处理,保证数据安全。

3. 死锁线程

在这里插入图片描述

from threading import Thread, currentThread, Lock
import time
A_lock = Lock()
B_lock = Lock()


class MyThread(Thread):
    
    def run(self):
        self.func1()
        self.func2()
        
    def func1(self):
        A_lock.acquire()
        print(f'{self.name}拿到A锁')
        
        B_lock.acquire()
        print(f'{self.name}拿到B锁')
        
         B_lock.release()
        print(f'{self.name}释放了B锁')

        A_lock.release()
        print(f'{self.name}释放了A锁')


    def func2(self):

        B_lock.acquire()
        print(f'{self.name}拿到了B锁')

        time.sleep(1)
        A_lock.acquire()
        print(f'{self.name}拿到了A锁')

        A_lock.release()
        print(f'{self.name}释放了A锁')

        B_lock.release()
        print(f'{self.name}释放了B锁')


if __name__ == '__main__':

    for i in range(3):
        t = MyThread()
        t.start()
    print('====主')
        

小结:

  • 虽然锁可以保证数据的安全,但是锁多了之后,容易造成死锁现象。进程锁同理
  • 如果以后项目中真的需求两把以上的锁才能解决问题,那么我们就不用这种同步锁(互斥锁)了,我要用递归锁。

4. 递归锁

  • 引子

    递归锁就是一把锁,这一把锁可以所多次,也可以释放多次,递归锁上有引用计数功能,锁一次+1一次,解锁一次,-1一次,递归锁不允许其他的线程或者进程抢夺知道递归锁上的引用计数为0时。

  • 测试

    from threading import Thread, RLock
    import time
    
    A_lock = RLock()
    B_lock = A_lock
    
    class MyThread(Thread):
    
        def run(self):
            self.func1()
            self.func2()
    
        def func1(self):
            A_lock.acquire()
            print(f'{self.name}拿到了A锁')
    
            B_lock.acquire()
            print(f'{self.name}拿到了B锁')
    
            B_lock.release()
            print(f'{self.name}释放了B锁')
    
            A_lock.release()
            print(f'{self.name}释放了A锁')
    
    
        def func2(self):
    
            B_lock.acquire()
            print(f'{self.name}拿到了B锁')
    
            time.sleep(1)
            A_lock.acquire()
            print(f'{self.name}拿到了A锁')
    
            A_lock.release()
            print(f'{self.name}释放了A锁')
    
            B_lock.release()
            print(f'{self.name}释放了B锁')
    
    
    if __name__ == '__main__':
    
        for i in range(3):
            t = MyThread()
            t.start()
        print('====主')
    
  • 进程递归锁:

5. 信号量

5.1 引子

信号量其实也是锁,但是这个锁比较特殊,之前我们讲的互斥锁就是同一时间只允许一个进程(线程)持有这把锁,知道释放掉,其他进程才可以竞争这把锁。而信号量同时可以允许N个进程(线程)持有这把锁,一个或者几个释放掉,其他的一个或者几个才可以进入。

举一个形象但是不文明的例子:信号量就是公共厕所。5个坑位,同事一个时刻只能5个人进入,怎么保证5个人?门口放5把钥匙,拿一个进一个月。当5把钥匙都被取走之后,剩下的人想进入只能等着,等有人释放完毕,将钥匙放到门口,其他的人再去争抢这把钥匙,这就是信号量。

from threading import Thread, currentThread, Semaphore
import time
import random


def go_wc(sem):
    sem.acquire()
    print(f'{currentThread().getName()}成功抢到坑位')
    time.sleep(random.randint(1, 3))
    print(f'{currentThread().getName()}成功结束')
  

if __name__ == '__main__':
    sem = Semaphore(5)
    for i in range(20):
        t = Thread(target=go_wc, args=(sem,))
        t.start()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值