python 线程 ~~ ~~~为面试开辟VIP通道~~~~~测试、死锁、全局变量共享、守护主线程等。。。。。。(2)

简介: python 线程 ~~ ~~~为面试开辟VIP通道~~~~~测试、死锁、全局变量共享、守护主线程等。。。。。。(2)

5、线程之间共享全局变量

# TODO 线程之间共享全局变量
import threading
import time
my_list=[]
#写入数据
def write_data():
    for i in range(5):
        my_list.append(i)
        time.sleep(0.1)
    print("write_data",my_list)
# 读取数据
def read_data():
    print("read_data",my_list)
if __name__ == '__main__':
    #  创建写入数据线程
    write_dataThred=threading.Thread(target=write_data)
    # 创建读取数据线程
    read_dataThred=threading.Thread(target=read_data)
    #开启进程
    write_dataThred.start()
    # 主线程等待写入线程执行完成以后代码再继续往下执行
    write_dataThred.join()# 等待子线程执行之后再执行下一次代码,不加这行你会发现read_data  读不到数据
    print("开始读取数据")

结果:image.pngread_data 哪去了??????image.png从上图可以发现只要重新启动read_dataThred线程就可以了你难道认为这样就可以了吗,太天真了。-_-下面再引入一个例子。

# TODO 线程之间共享全局变量出现问题     问题:线程不一致,交替拿变量      解决方法     保持线程同步,同一时刻只能有一个线程去操作全局变量    两种方式   线程等待  +  互斥所
import threading
#  创建函数,实现循环100万次,每次全局变量加一
g_num=0
# 每次全局变量加一
def sun_num():
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num",g_num)
# 每次全局变量加一
def sun_num2():
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num2", g_num)
if __name__ == '__main__':
    sun_numThred=threading.Thread(target=sun_num)
    sun_num2Thred=threading.Thread(target=sun_num2)
    #开启线程
    sun_numThred.start()
    sun_num2Thred.start()

结果:image.pngimage.png结果是出结果了,但是你们细看一下代码,你们不感觉这个答案有问题吗?有没有这样一个疑问,for循环,遍历共享变量,最后应该是1000000和2000000啊,怎么打印出来的是1000000和1456202,而且细心的你还会发现每次的大男孩不一样。想要解决问题应该怎么办呢?问题总结:线程不一致,交替拿变量 解决方法 保持线程同步,同一时刻只能有一个线程去操作全局变量 两种方式 线程等待 + 互斥所线程等待:join出场ticle/details/123494962

# TODO 线程之间共享全局变量出现问题     问题:线程不一致,交替拿变量      解决方法     保持线程同步,同一时刻只能有一个线程去操作全局变量    两种方式   线程等待  +  互斥所
import threading
#  创建函数,实现循环100万次,每次全局变量加一
g_num=0
# 每次全局变量加一
def sun_num():
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num",g_num)
# 每次全局变量加一
def sun_num2():
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num2", g_num)
if __name__ == '__main__':
    sun_numThred=threading.Thread(target=sun_num)
    sun_num2Thred=threading.Thread(target=sun_num2)
    #开启线程
    sun_numThred.start()
    # # TODO 方法一
    sun_numThred.join()
    sun_num2Thred.start()

结果:image.png线程等待,当前线程等待其他线程执行某些操作,典型场景就是生产者消费者模式,在任务条件不满足时,等待其他线程的操作从而使得条件满足。等到其他线程完成操作释放后再分配线程。当前线程获得资源继续执行操作。

6、互斥锁

****互斥锁 Lock():在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

互斥锁三步骤 ~~~ 创建一把锁==》上锁==》释放锁 三步走

#  TODO   互斥锁  Lock()
import threading
# # TODO 创建一把锁==》上锁==》释放锁   三步走
# mutext=threading.Lock()
# mutext.acquire()
# mutext.release()
#定义全局变量
g_num=0
# 创建一把锁
mutext=threading.Lock()
# 每次全局变量加一
def sun_num():
    # TODO   上锁
    mutext.acquire()
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num",g_num)
    # TODO  释放锁
    mutext.release()
# 每次全局变量加一
def sun_num2():
    # TODO 上锁
    mutext.acquire()
    for i in range(1000000):
        global g_num
        g_num+=1
    print("sun_num2", g_num)
if __name__ == '__main__':
    sun_numThred=threading.Thread(target=sun_num)
    sun_num2Thred=threading.Thread(target=sun_num2)
    #开启线程
    sun_numThred.start()
    sun_num2Thred.start()

结果:image.png是不是非常神奇。主义事项:一、互斥锁就三步骤 1、创建一把锁 2、上锁 3、释放锁 。二、保证共享数据操作的完整性三、等当前上锁线程执行完成,释放锁后其他线程才能申请资源

7、死锁

死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去

# TODO  死锁
import threading
import time
# 创建互斥锁
lock=threading.Lock()
def get_value(index):
    #上锁
    lock.acquire()
    print(threading.current_thread())
    my_list=[3,4,7,2]
    # 根据下标释放取值
    if index>=len(my_list):
        print("下标越界:",index)
        # TODO  当下标越界了释放锁,让后面线程继续取值
        # lock.release()
        return
    value=my_list[index]
    print(value)
    time.sleep(0.2)
    #释放锁
    # lock.release()
if __name__ == '__main__':
    #模拟大量线程取值
    for i in range(30):
        sub_thred=threading.Thread(target=get_value,args=(i,))
        sub_thred.start()

结果:image.png注释掉释放锁的操作,线程刚执行就卡住了,产生了死锁。

打开释放所操作

# TODO  死锁
import threading
import time
# 创建互斥锁
lock=threading.Lock()
def get_value(index):
    #上锁
    lock.acquire()
    print(threading.current_thread())
    my_list=[3,4,7,2]
    # 根据下标释放取值
    if index>=len(my_list):
        print("下标越界:",index)
        # TODO  当下标越界了释放锁,让后面线程继续取值
        lock.release()
        return
    value=my_list[index]
    print(value)
    time.sleep(0.2)
    #释放锁
    lock.release()
if __name__ == '__main__':
    #模拟大量线程取值
    for i in range(30):
        sub_thred=threading.Thread(target=get_value,args=(i,))
        sub_thred.start()

结果:image.png1、因为我们是用方式传参,循环30次,索引0~29。

2、我们会发现我们在判断越界后,因为释放锁所以仍会输出。

3、加入互斥锁解除了死锁危机。

目录
相关文章
|
15天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
9天前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
28 4
|
11天前
|
JSON 测试技术 持续交付
自动化测试与脚本编写:Python实践指南
自动化测试与脚本编写:Python实践指南
16 1
|
16天前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
2天前
|
Web App开发 测试技术 数据安全/隐私保护
自动化测试的魔法:使用Python进行Web应用测试
【10月更文挑战第32天】本文将带你走进自动化测试的世界,通过Python和Selenium库的力量,展示如何轻松对Web应用进行自动化测试。我们将一起探索编写简单而强大的测试脚本的秘诀,并理解如何利用这些脚本来确保我们的软件质量。无论你是测试新手还是希望提升自动化测试技能的开发者,这篇文章都将为你打开一扇门,让你看到自动化测试不仅可行,而且充满乐趣。
|
23天前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
26天前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
51 0
|
Python
python修改全局变量一定要加global吗?
python修改全局变量一定要加global吗?
233 0
python修改全局变量一定要加global吗?
|
9天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
2天前
|
存储 人工智能 数据挖掘
从零起步,揭秘Python编程如何带你从新手村迈向高手殿堂
【10月更文挑战第32天】Python,诞生于1991年的高级编程语言,以其简洁明了的语法成为众多程序员的入门首选。从基础的变量类型、控制流到列表、字典等数据结构,再到函数定义与调用及面向对象编程,Python提供了丰富的功能和强大的库支持,适用于Web开发、数据分析、人工智能等多个领域。学习Python不仅是掌握一门语言,更是加入一个充满活力的技术社区,开启探索未知世界的旅程。
12 5