<<返回python首页 python

《Python 应用案例》

Python标准库:多线程

刺绣,线,牙线,缝纫,工艺,羊毛,多色

Python的标准库提供了两个模块:_threadthreading_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,使用threading这个高级模块就足够了。

创建并使用多线程

import time, threading


# 新线程要执行的代码:
def say_some():
    print('--------线程 [{}] 开始运行...'.format(threading.current_thread().name))
    n = 0
    while n < 5:
        n = n + 1
        print('thread [{}] >>> [{}]'.format(threading.current_thread().name, n))
        time.sleep(n)
    print('线程 [{}] 结束运行...'.format(threading.current_thread().name))


def demo1():
    print('--------线程 [{}] 开始运行...'.format(threading.current_thread().name))
    t = threading.Thread(target=say_some, name='SaySomeThread')
    t.start()
    t.join()  # 线程结束后继续执行
    print('线程 [{}] 结束运行...'.format(threading.current_thread().name))

demo1()

线程的锁

多线程和多进程最大的不同在于,多进程中,同一个变量,

各自有一份拷贝存在于每个进程中,互不影响,而多线程中,

所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,

因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

所以,和多进程相比,多线程需要对特定的变量加锁,保证其修该操作不会乱。

# 锁
lock = threading.Lock()


def run_thread(n):
    for i in range(100000):
        # 先要获取锁:
        lock.acquire()
        try:
            # 修改变量
            n = n + 1
        finally:
            # 改完了一定要释放锁:
            lock.release()

包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。

Python “伪”多线程原因:GIL锁

使用C、C++或Java来写特定死循环,直接可以把全部核心跑满,4核就跑到400%,

但是Python跑相同代码,只能将CPU跑到100%左右。

Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,

任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,

解释器就自动释放GIL锁,让别的线程有机会执行。

GIL全局锁实际上把所有线程的执行代码都给上了锁,

所以,多线程在Python中只能交替执行,

即使100个线程跑在100核CPU上,也只能用到1个核。

解决方案: 多进程

Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。

多个Python进程有各自独立的GIL锁,互不影响。

线程全局变量

# 创建全局ThreadLocal对象:
local_something = threading.local()

# 1  执行线程
def process_say_someting():
    # 获取当前线程关联的student:
    text = local_something.content
    print('Hello, %s (in %s)' % (text, threading.current_thread().name))


# 2  赋值线程
def process_thread(t):
    # 为该线程,绑定ThreadLocal的值:
    local_something.content = t
    process_say_someting()


t1 = threading.Thread(target=process_thread, args=('hhhhh',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('wwwwww',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
移动端设备除iPad Pro外,其它移动设备仅能阅读基础的文本文字。
建议使用PC或笔记本电脑,浏览器使用Chrome或FireFox进行浏览,以开启左侧互动实验区来提升学习效率,推荐使用的分辨率为1920x1080或更高。
我们坚信最好的学习是参与其中这一理念,并致力成为中文互联网上体验更好的学练一体的IT技术学习交流平台。
您可加QQ群:575806994,一起学习交流技术,反馈网站使用中遇到问题。
内容、课程、广告等相关合作请扫描右侧二维码添加好友。

狐狸教程 Copyright 2021

进入全屏