Python上多线程

多线程

之前对多进程的知识的总结:多进程

线程比进程单位更小,线程是一个基本的CPU执行单元。线程必须在某个进程中执行,一个进程可包含多个线程,但是只能有一个主线程。在多线程中,共享同个地址空间、打开的文件等资源;在多进程中,共享物理内存、、磁盘、打印机等资源。其中,线程按照作用不同可分为主线程、子线程、守护线程(后台线程)以及前台线程等。
在Python标准库中,提供的模块有thread和threading。其中,thread是低级模块,threading是高级模块,对thread进行了封装。

  1. 使用threading模块创建多线程
    同创建进程一样,threading模块中也提供两种方法创建多线程。分别是传入函数创建Thread实例和直接从threading.Thread中继承并创建线程类。
    测试程序threading_demo.py
# -*- coding: utf-8 -*-

import threading
import random, time

def run_thread(nums):
    print("当前线程 %s 正在运行..." % threading.current_thread().name)
    for num in nums:
        print("线程 %s 读取数据 %s" % (threading.current_thread().name, num))
        time.sleep(random.random())
    print("线程 %s 结束..." % threading.current_thread().name)

class MyThread(threading.Thread):
    def __init__(self, name, nums):
        threading.Thread.__init__(self, name=name)
        self.nums = nums

    def run(self):
        print("当前线程 %s 正在运行..." % threading.current_thread().name)
        for num in self.nums:
            print("线程 %s 读取数据 %s" % (threading.current_thread().name, num))
            time.sleep(random.random())
        print("线程 %s 结束..." % threading.current_thread().name)

if __name__ == '__main__':
    print("当前线程 %s 正在运行..." % threading.current_thread().name)

    thread1 = threading.Thread(target=run_thread, args=([i for i in range(1, 4)], ))
    thread2 = threading.Thread(target=run_thread, args=([i for i in range(4, 7)], ))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()

    thread3 = MyThread(name='thread3', nums=[i for i in range(1,4)])
    thread4 = MyThread(name='thread4', nums=[i for i in range(4,7)])
    thread3.start()
    thread4.start()
    thread3.join()
    thread4.join()

    print("线程 %s 结束..." % threading.current_thread().name)
  1. 线程同步
    在多线程中,线程同步是很为重要的。这是为了防止多个线程同时对同一个数据进行了修改。在Thread对象中,Lock和RLock可以实现简单的线程同步,通过将数据操作放入acquire和release操作中。Lock和RLock的主要区别在于RLock可以多次执行acquire操作,但是有多少个acquire操作之后就需要有多少个release操作,如果对Loak执行两次acquire操作则会发生死锁。
    测试程序threading_synchronization.py
import threading
import random, time


def run_thread():
    global num
    for i in range(4):
        rlock.acquire()
        print("线程 %s 已锁定,此时 num = %s"
              %(threading.current_thread().name, num))
        num = random.random()
        rlock.release()
        print("线程 %s 已解锁,此时 num = %s"
              %(threading.current_thread().name, num))

if __name__ == '__main__':
    print("当前线程 %s 正在运行..." % threading.current_thread().name)

    rlock = threading.RLock()
    num = random.random()
    thread1 = threading.Thread(target=run_thread)
    thread2 = threading.Thread(target=run_thread)
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()

    print("线程 %s 结束..." % threading.current_thread().name)

需要注意的是,在使用CPython解释器的时候,会存在全局解释器锁GIL的概念。该锁主要是为了在不同线程同时访问一数据时,对数据提供保护机制。这隐含着说明任何python程序,在任何时候都只有一个线程在执行,而不管处理器的数量。正是因为这把锁的存在,所以对于IO密集型的任务,使用多线程更快,而对于CPU密集型的任务,可以通过使用多进程代替多线程,避开GIL。而在CPython解释器中之所以不移除GIL,主要是移除之后解释器的执行效率会更低,同时使用GIL的话会使得初学者的门槛更低。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值