给自己的Python小笔记-Python-想同时执行多个Function函数吗? 那来试试这个平行设计模组- 多执行绪(Multi-Threading)使用教学

為自己Coding
·
·
IPFS
·


Github连结

摄影师:luis gomes,连结:Pexels


1. 多执行绪(Multi- Threading),或称多线程是什么?

  • 执行绪(thread)为作业系统(OS)排程的最小单位
  • 多执行绪是指当我们要在同一个Python档里执行多组的程式(ex. 不同function),而且是要同时平行执行时


2. 为什么要使用多执行绪(Multi-Threading)?

现代的电脑几乎都具有相当多的核心,而我们执行程式,通常只会使用到一颗核心,但我们想要充分的发挥多核心硬体的运算能力,就需要使用多执行绪(Multi-Threading)或多行程Mult-Processing)等的平行运算技术


3. 为什么要使用Python来实现多执行绪(Multi-Threading),并不会更快?

依照多执行绪(Mult. Threading)的平行设计,我们的程式不是应该运行的更快吗,为什么使用Python撰写时, 不仅没有更快,反而有时候更慢,其他语言在执行多执行续(Multi- Threading),是支援多核CPU同时执行多个执行绪的,但Python受到GIL(Global Interpreter Lock)的限制,导致无论在单核还是多核都是只支援一次只执行一个执行绪

GIL(Global Interpreter Lock) 原本是设计来保护数据的,一个执行绪要执行要先拿到GIL,才能进入到CPU之中执行,反之没有拿到GIL,就不能进入


4. 这样Python还要用多执行绪(Multi-Threading)吗?

GIL(Global interpreter Lock)只会影响那些需要很大程度依赖CPU的程式,像是要做大量计算的数据预处理算法,而如果我们的程式只会影响到I/O操作,像是网路应用与手机控制等,就非常适合使用多执行绪(Multi-Threading), 因为它本来就需要花很多时间等待。


5. Python的解决办法

改用多行程(Multi-Processing)的方式来执行,就不会受到GIL (Global Interpreter Lock)限制,我会在之后的文章中写一篇来教大家喔



实作




6. 获取执行绪(thread)的资讯方法

  1. threading.active_count(): 当前活动中的执行续数量,也可以写成threading.activeCount()
  2. threading.current_thread: 当前正在使用的执行续,或写成threading.currentThread()
  3. threading.enumerate(): 当前活动中的所有执行续资讯

程式范例

## 导入套件import threading
​
def threading_example():
  ## 也可以写成threading.activeCount()、threading.currentThread()
  print('活动中的执行续数量: ', threading.active_count())
  print('当前正在使用的执行续: ', threading.current_thread())
  print('当前正在使用的执行续名称: ', threading.current_thread().name)
  print('目前活动中的执行续资讯: ', threading.enumerate)

  ​
if __name__ == '__main__':
  threading_example()

执行结果

活动中的执行续数量: 5
当前正在使用的执行续: <_MainThread(MainThread, started 14512)>
当前正在使用的执行续名称: MainThread
目前活动中的执行续资讯: <function enumerate at 0x000002A0E9831B88>

7. 创建执行续(thread)的方法

  • 函数格式
threading.Thread(target = function, name = '执行叙明称', args = variable)
  • 参数说明
  1. target: 指定执行的函式(工作)
  2. name: 设定执行绪的名称
  3. args: 欲带入函式的参数,但要以list的形式传入
  • 程式码范例1:
 ## 导入套件import threading
​
## 新建的执行绪将执行此函数(工作)
def added_thread_job():
  print('新增加的执行续: ', threading.current_thread())
  print('新增加的执行续名称: ', threading.current_thread().name)
  print('活动中的执行续数量: ', threading.active_count())
​
## 创建新执行绪def added_threading_example():
  ## 新称的执行绪  added_thread = threading.Thread(target = added_thread_job, name = 'new_added_thread')
​
  ## 启动执行绪  added_thread.start()

  ​
if __name__ == '__main__':
  added_threading_example()

执行结果

新增加的执行续: <Thread(new_added_thread, started 17184)>
新增加的执行续名称: new_added_thread
活动中的执行续数量: 6
  • 程式码范例2: 带入参数的用法
import threading
​
def added_thread_job(a):
  ## 印出传入的参数  print(a)

    print('新增加的执行续: ', threading.current_thread())
  print('新增加的执行续名称: ', threading.current_thread().name)
  print('活动中的执行续数量: ', threading.active_count())

  def added_threading_example():
  ## 欲传入added_thread_job的参数  text = ['Threading Learning']

    ## 新称执行绪  added_thread = threading.Thread(target = added_thread_job, name = 'new_added_thread', args = text)

    ## 启动执行绪  added_thread.start()

  if __name__ == '__main__':
  added_threading_example()

执行结果

Threading Learning
新增加的执行续: <Thread(new_added_thread, started 11884)>
新增加的执行续名称: new_added_thread
活动中的执行续数量: 6

8. 执行创建的执行绪(thread)方法

  • 函式功能介绍:
  1. start(): 启动执行绪,执行工作
  2. join(): 等到执行绪终止后, 才会往下执行程式码
  3. isAlive(): 检查执行绪是否还在执行
  4. getName(): 取得thread名称
  5. setName(): 设定thread名称

1. 基本用法

  • 范例: .start()、isAlive()、setName()、getName()用法

提醒: 每次执行结果不同,是因为每次执行绪的执行时间可能不同,所以会有先后执行的问题

import threading
​
def added_thread_job():
  print('新增加的执行续: ', threading.current_thread())
  print('新增加的执行续名称: ', threading.current_thread().name)
  print('活动中的执行续数量: ', threading.active_count())

  def added_threading_example():
  ## 新增执行绪  added_thread = threading.Thread(target = added_thread_job, name = 'new_added_thread_1')

    ## 设定thread名称  added_thread.setName('new_added_thread_2')

    ## 取得thread名称  print(added_thread.getName())

    ## 启动执行绪  added_thread.start()

    ## 检查执行绪是否还在执行  print(added_thread.isAlive())


    if __name__ == '__main__':
  added_threading_example()



      ​
​
​

执行结果

new_added_thread_2
新增加的执行续: <Thread(new_added_thread_2, started 3056)>
新增加的执行续名称: new_added_thread_2
活动中的执行续数量: True
6

2. join()用法- 解决执行绪还没执行完,就先往下执行下一段程式的方法

我会透过下面的例子来带大家了解join的用法,以及有没有使用join的差别

  • 程式码范例1: 未使用join的状况下

重点: 还没加上.join(),遇到的问题

从下面的执行结果可以看出,执行绪还未执行完added_thread_job()(工作),程式就先执行了print('Next Code'),而我们要的应该事先执行完added_thread_job(),再执行print('Next Code'), 再执行print('Next Code'), 这是因为执行时间所造成的影响

## 导入套件import threading
import time
​
def added_thread_job():
  print("Thread Start")

    ## 执行工作, 工作内容要执行20次,每次要执行0.1秒,来将执行工作时间拉长  for i in range(20):
    time.sleep(0.1)
    print('execute job' + str(i))
​
  print('Thread Finish')

  def added_thread_example():
  ## 新建执行绪  added_thread = threading.Thread(target = added_thread_job, name = 'new_added_thread')

    ## 执行执行绪  added_thread.start()

    print('Next Code')


    if __name__ == '__main__':
  added_thread_example()

执行结果

Thread Start
Next Code
execute job0
execute job1
execute job2
execute job3
execute job4
execute job5
execute job6
execute job7
execute job8
execute job9
execute job10
execute job11
execute job12
execute job13
execute job14
execute job15
execute job16
execute job17
execute job18
execute job19
Thread Finish
  • 程式范例2: 使用join()后的结果

重点:加上join()后的解决结果

执行结果可以看出,程式会先等待我们新增的执行绪执行完后,再执行下一段程式

## 导入套件import threading
import time
​
def added_thread_job():
  print("Thread Start")

    ## 执行工作, 工作内容要执行20次,每次要执行0.1秒,来将执行工作时间拉长  for i in range(20):
    time.sleep(0.1)
    print('execute job' + str(i))
​
  print('Thread Finish')

  def added_thread_example():
  ## 新建执行绪  added_thread = threading.Thread(target = added_thread_job, name = 'new_added_thread')

    ## 执行执行绪  added_thread.start()

    ## 等到此执行绪执行完  added_thread.join()

    print('Next Code')


    if __name__ == '__main__':
  added_thread_example()

执行结果

Thread Start
execute job0
execute job1
execute job2
execute job3
execute job4
execute job5
execute job6
execute job7
execute job8
execute job9
execute job10
execute job11
execute job12
execute job13
execute job14
execute job15
execute job16
execute job17
execute job18
execute job19
Thread Finish
Next Code

补充: 两个执行绪一起执行的状况这边我把第一条执行绪.join放在执行print("Next Code")前执行完毕,由于第二条执行绪执行的工作少于第一条执行绪,所以会在执行完第一条执行绪前执行完毕实验:大家可以根据自己的调整.join的位置

  • 程式范例:
 ## 导入套件import threading
import time
​
## 第一条执行绪执行的工作def added_thread_job1():
  print("Thread 1 Start")

    ## 执行工作, 工作内容要执行5次,每次要执行0.1秒,来将执行工作时间拉长  for i in range(5):
    time.sleep(0.1)
    print('execute job' + str(i))
​
  print('Thread 1 Finish')
​
## 第二条执行绪执行的工作def added_thread_job2():
  print("Thread 2 Start")

    ## 执行工作, 工作内容要执行2次,每次要执行0.1秒,来将执行工作时间拉长  for i in range(2):
    time.sleep(0.1)
    print('execute job' + str(i))
​
  print('Thread 2 Finish')
​
​

  def added_thread_example():
  ## 新建执行绪  added_thread1 = threading.Thread(target = added_thread_job1, name = 'new_added_thread1')
  added_thread2 = threading.Thread(target = added_thread_job2, name = 'new_added_thread2')


      ## 执行第一条执行绪  added_thread1.start()

    ## 执行第二条执行绪  added_thread2.start()

    ## 等到第一条执行绪执行完  added_thread1.join()

    ## 等到第二条执行绪执行完  added_thread2.join()

    print('Next Code')
​
if __name__ == '__main__':
  added_thread_example()
​

执行结果

Thread 1 Start
Thread 2 Start
execute job0
execute job0
execute job1
execute job1
Thread 2 Finish
execute job2
execute job3
execute job4
Thread 1 Finish
Next Code

3. Queue 伫列

  • 说明: 用来储存多执行绪的个别运算结果,最后再从Queue中取得最终结果

重要: 由于多执行绪(或称多线程),不能像平常那样使用return来回传函数(function)结果,所以需要用到Queue的方式来取得函数(function)的结果

  • Queue的使用方法
  • 首先: 我们需要导入Queue的套件: from queue import Queue
  • 再来: q.put()来回传函数(function)结果到Queue中,与return的意思是一样的
  • 最后: q.get()按顺序从序列中取得结果值,一次只取一个值
  • Queue的实作步骤范例:

Step1 : 导入Queue的套件

from queue import Queue

Step2:建立执行绪欲执行的函数(工作)

重要提醒: 由于Queue没有return这个方法,所以这边需要使用queue.put()来取的回传值

## 定义执行绪欲直行的函数(工作)
def thread_job(l,q):
  ## 将资料集做平方运算  for i in range(len(l)):
    l[i] = l[i]**2

    ## 回传值: 回传到Queue中  q.put(l)

Step3:定义多执行绪(Multi-Threading)函数

a.

 ## 定义多执行绪的函数def multi_threading():
  ## 启用Queue伫列  q = Queue()

         ## 用来装所有创建的执行绪  threads = []

         ## 自行定义的数据集  data = [[2,4,8],[2,6,10],[3,7,9],[8,9,3],[5,5,6]]

说明: "q = Queue()" 我将q定义为Queue()伫列,表示之后使用q.put(),就会回传到q这个伫列之中

b.

由于我的资料有五组,所以我定义五个执行绪来运算,并将这些新定义的执行绪(Thread)放入thread串列里

  ## 定义五个执行绪,并放入threads里  for d in range(5):

        ## 定义执行绪    t = threading.Thread(target = thread_job, args = (data[d], q))

           ## 启用执行绪    t.start()

           ## 放入threads里    threads.append(t)

c.

使用.join()将五个执行绪家道主执行绪之中,并确保它们都有执行完毕,才进行下一步

  ## 使用.join()将五个执行绪家道主执行绪之中,并确保它们执行完毕,才进行下一步  for thread in threads:
    thread.join()

d.

创建一个串列(list)来装五个执行绪执行完毕后保存于Queue伫列中的结果,使用q.get()来将它们取出伫列Queue

  ## 创建一个串列(list)来装载结果  results = []

         ## 将Queue中的结果取回  for r in range(5):
    results.append(q.get())

         print(results)

完整程式码

## 导入套件import threading
import time
## 导入Queue所需的套件from queue import Queue
​
## 定义执行绪欲直行的函数(工作)
def thread_job(l,q):
  ## 将资料集做平方运算  for i in range(len(l)):
    l[i] = l[i]**2

    ## 回传值: 回传到Queue中  q.put(l)
​
## 定义多执行绪的函数def multi_threading():
  ## 启用Queue伫列  q = Queue()

         ## 用来装所有创建的执行绪  threads = []

         ## 自行定义的数据集  data = [[2,4,8],[2,6,10],[3,7,9],[8,9,3],[5,5,6]]
​
  ## 定义五个执行绪,并放入threads里  for d in range(5):

        ## 定义执行绪    t = threading.Thread(target = thread_job, args = (data[d], q))

           ## 启用执行绪    t.start()

           ## 放入threads里    threads.append(t)


               ## 使用.join()将五个执行绪家道主执行绪之中,并确保它们执行完毕,才进行下一步  for thread in threads:
    thread.join()


                ## 创建一个串列(list)来装载结果  results = []

         ## 将Queue中的结果取回  for r in range(5):
    results.append(q.get())

         print(results)


              if __name__ == '__main__':
  multi_threading()

执行结果

[[4, 16, 64], [4, 36, 100], [9, 49, 81], [64, 81, 9], [25, 25, 36]]

4. GIL(Global Interpreter Lock)

前面有提到受到GIL(Global Interpreter Lock )限制,Python的多执行绪(Multi-Threading)执行速度并没有比较快,这边我们来测试一下是否是真的

  • 程式码范例: 我一个采用多执行绪(Multi-Threading),一个不采用,然后比较两者的执行速度
## 导入套件import threading
import time
import copy
## 导入Queue所需的套件from queue import Queue
​
## 多执行绪欲直行的函数(工作)
def thread_job(l,q):
  ## 计算数据串列中的总和  total = sum(l)

    ## 回传结果  q.put(total)
​

  ## 定义多执行绪的函数def multi_threading(l):
  ## 启用Queue伫列  q = Queue()
  ## 用来装执行绪  threads = []

    ## 定义五个执行绪,并放入threads里  for d in range(5):
    ## 定义执行绪    t = threading.Thread(target = thread_job, args = (copy.copy(l), q), name = 'Thread %d' % d)

        ## 启用执行绪    t.start()

        ## 放入threads里    threads.append(t)


              ## 使用.join()将这五个执行绪加到主执行绪之中,并确保它们都有执行完毕,才进行下一步  for thread in threads:
    thread.join()

      ## 创建一个串列(list)来装结果  results = []

    ## 将Queue中的运算结果取回  for r in range(5):
    results.append(q.get())


          print('Multi Threading Method: ', results[0])


      ## 定义不使用Multi-Threading的函数def normal_method(l):
  total = sum(l)
  print('Normal Method: ', total)


        if __name__ == '__main__':
  ## 创建一组数据串列  l = list(range(1000000))
​
  ## 记下当下的时间  c_t = time.time()
​
​
  ## 执行一般运算的方法  normal_method(l*5)
​
  ## 纪录执行时间  nt = time.time() - c_t
​
  ## 印出一般的执行时间  print('Normal Time: ', nt)
​
  ## 记下当下时间  c_t1 = time.time()
​
  ## 执行Multi-Threading运算  multi_threading(l)
​
  ## 纪录执行的时间  mt = time.time() - c_t1
​
  ## 印出Multi Threading的执行时间  print('Multi-Threading: ', mt)
​
  ## 一般与多执行绪的执行时间差  print('Normal Time - Multi-Threading: ', nt - mt)

为什么normal_method(l*5)要把数据乘以5说明:因为我们使用五个执行绪同时执行同一笔数据,就等同于一般状况下做五次,所以要乘5,才能比较运算速度喔

执行结果

Normal Method: 2499997500000
Normal Time: 0.15358924865722656
Multi Threading Method: 499999500000
Multi-Threading: 0.1486034393310547
Normal Time - Multi-Threading: 0.004985809326171875

结果: 理论来说,我们使用五个执行绪来执行,所运算的时间应该要只有一般状况下的1/5,但从执行结果来看,Multi-Threading在速度上并没有比一般快,或只有快一点点

5. Lock 锁住

  • 使用时机在使用多执行绪(Multi-Threading)时,每个执行绪都会同时执行,但有时候我们不能让多个执行绪同时执行,像是我们不希望同时写入档案,这样可能会造成错乱,简单来说就是我们希望执行绪等待上一个执行绪完成工作后,才能进行工作,一次只允许一个执行绪执行工作,这时我们就会使用lock
  • 两个重要的lock使用方法
  • i. Lock.acquire: 当执行绪使用acquire时,就会获得执行的权利,这时候只有它能够执行,其他执行绪要等它执行完毕,才能执行
  • ii. Lock.release: 当执行绪使用release,就会释放执行的权利,让下一个呼叫acquire的执行绪获取执行权利
  • 程式码范例1: 未使用lock的状况
## 导入套件import threading
​
## 定义两个函数(工作) 分别由两个执行绪来执行def thread_job1():
  ## 将result 定义为全域变数  global result

    ## 执行20次,每次将result值加1
  for i in range(20):
    result += 1
    print("thread job1: ", result)


        def thread_job2():
  ## 将result 定义为全域变数  global result

    ## 执行20次,每次将result值加1
  for i in range(20):
    result += 2
    print("thread job2: ", result)
​
if __name__ == '__main__':
  result = 0

    ## 定义两条执行绪,分别执行两种函数(工作)
  thread1 = threading.Thread(target = thread_job1)
  thread2 = threading.Thread(target = thread_job2)


      ## 执行  thread1.start()
  thread2.start()

    ## 执行完毕  thread1.join()
  thread2.join()

执行结果

thread job1: 1
thread job1: 2
thread job1: 3
thread job1: 4
thread job1: 5
thread job1: 6
thread job1: 7
thread job1: thread job2: 10
8
thread job1: 11
thread job1: 12
thread job1: 13thread job2: 15
thread job2: 17
thread job2: 19
thread job2:
 thread job1: 22
thread job1: 23
thread job1: 24
thread job1: 25
thread job1: 26
thread job1: 27
thread job1: 28
thread job1: 29
thread job1: 30
21
thread job2: 32
thread job2: 34
thread job2: 36
thread job2: 38
thread job2: 40
thread job2: 42
thread job2: 44
thread job2: 46
thread job2: 48
thread job2: 50
thread job2: 52
thread job2: 54
thread job2: 56
thread job2: 58
thread job2: 60

重点: 大家会发现每次执行的结果都不同,执行结果也显示的非常乱,所以接下来我们要使用Lock来解决这个问题

  • 程式码范例2: 使用threading.Lock()来实现lock的方法
## 导入套件import threading
​
## 定义两个函数(工作) 分别由两个执行绪来执行def thread_job1():
  ## 将lock、result定义为全域变数  global lock, result

    ## 获取执行权  lock.acquire()

    ## 执行20次,每次将result值加1
  for i in range(20):
    result += 1
    print("thread job1: ", result)

      ## 释放执行权  lock.release()


    def thread_job2():
  ## 将locl、result定义为全域函数  global lock, result

    ## 获取执行权  lock.acquire()

    ## 执行20次,每次将result值加2
  for i in range(20):
    result +=2
    print("thread job2: ", result)

      ## 释放执行权  lock.release()


    if __name__ == '__main__':

    ## 定义lock的方法  lock = threading.Lock()

    result = 0

    ## 定义两条执行绪,分别执行两种函数(工作)
  thread1 = threading.Thread(target = thread_job1)
  thread2 = threading.Thread(target = thread_job2)

    ## 执行  thread1.start()
  thread2.start()


      ## 执行完毕  thread1.join()
  thread2.join()

执行结果

thread job1: 1
thread job1: 2
thread job1: 3
thread job1: 4
thread job1: 5
thread job1: 6
thread job1: 7
thread job1: 8
thread job1: 9
thread job1: 10
thread job1: 11
thread job1: 12
thread job1: 13
thread job1: 14
thread job1: 15
thread job1: 16
thread job1: 17
thread job1: 18
thread job1: 19
thread job1: 20
thread job2: 22
thread job2: 24
thread job2: 26
thread job2: 28
thread job2: 30
thread job2: 32
thread job2: 34
thread job2: 36
thread job2: 38
thread job2: 40
thread job2: 42
thread job2: 44
thread job2: 46
thread job2: 48
thread job2: 50
thread job2: 52
thread job2: 54
thread job2: 56
thread job2: 58
thread job2: 60

6. Semaphore旗标

  • 说明:功能类似于Lock,但Lock一次只允许一个执行绪进行工作,而Semaphore允许多个执行绪同时工作,但要限制数量,它也是用acquire来获取执行权,release来释放执行权,但不同的是Semaphore在执行这两个函数时,多了一个计数器的概念,当acquire时会-1,release时会+1,减到为0时,下一个执行绪就需要正在执行工作执行绪release释放权限后,才能执行
  • 使用时机:因为系统的资源有限,像是CPU或记忆体限制,在执行很耗资源的程式时,我们希望限制同时执行工作的执行绪数量,才不会造成系统执行很慢
  • 使用方法: threading.Semaphore()函数里面的参数为限制同时执行的执行绪数量,像是threading.Semaphore(2),代表同时限制两个执行绪执行
  • 程式码范例:
 ## 导入套件import threading
import time
from queue import Queue
​
​
## 定义一个类别class Worker(threading.Thread):
  ## 初始化  def __init__(self, queue, name, semaphore):
    ## 建立执行绪    threading.Thread.__init__(self)
    self.queue = queue
    self.name = name
    self.semaphore = semaphore


      ## 执行的工作  def run(self):
    ## 当Queue中还有资料没有被拿出来时    while self.queue.qsize() > 0:
      ## 取出Queue中的资料      msg = self.queue.get()

          ## 取得执行权      semaphore.acquire()
      print("%s acquire the Semaphore" % self.name)

            ## 只允许有限的执行绪同时执行      print("%s get %s from my_queue" % (self.name, msg))
      time.sleep(1)

            ## 释放执行权      print("%s released the Semaphohre" % self.name)
      self.semaphore.release()

      if __name__ == '__main__':
  ## 启用Queue 伫列  my_queue = Queue()
​
  ## 将数据塞进Queue中  for i in range(6):
    my_queue.put("Data %d" % i)
​
​
  ## 建立旗标,并限制同时只可以有两个执行绪获取执行权  semaphore = threading.Semaphore(2)
​
  ## 建立类别,同时建立执行绪  person1 = Worker(my_queue, 'Jack', semaphore)
  person2 = Worker(my_queue, 'Tom', semaphore)
  person3 = Worker(my_queue, 'Cathy', semaphore)
​
  ## 启动执行绪  person1.start()
  person2.start()
  person3.start()

提醒: 这边执行的函数名称一定要使用run才会执行

执行结果

Jack acquire the Semaphore
Jack get Data 0 from my_queue
Tom acquire the Semaphore
Tom get Data 1 from my_queue
Jack released the Semaphohre
Jack acquire the Semaphore
Jack get Data 3 from my_queue
Tom released the Semaphohre
Tom acquire the Semaphore
Tom get Data 4 from my_queue
Jack released the Semaphohre
Jack acquire the Semaphore
Jack get Data 5 from my_queue
Tom released the Semaphohre
Cathy acquire the Semaphore
Cathy get Data 2 from my_queue
Jack released the Semaphohre
Cathy released the Semaphohre

7. RLock

  • 说明: 为一个可以重复取得执行权的方法,与Lock功能类似,但是它可以允许同一个执行绪,重复取得执行的权利,RLock也有计数器的概念,但与Semaphore不同的点在于acquire获取权限的时候会+1,release释放权限时会-1,刚好与Semaphore相反,当递减到0时,才会真的释放执行权,大于0的时候,其它执行绪都不能获得执行权
  • 例子说明:

这边我使用lock来示范,如下面,当重复acquire一次时,因为执行权已经被锁定了,所以会被挡住

## 启动lock
lock = threading.Lock()
​
## 获取执行权lock.acquire()
​
## 再次获取执行权时,会被挡住lock.acquire()
​

使用RLock就不会被挡住啰!!

 ## 启动RLock
rlock = threading.RLock()
​
## 取得执行权rlock.acquire()
​
## 重复取得执行权,不会被挡住rlock.acquire()
​
## 释放执行权rlock.release
​
## 再次释放执行权rlock.release()


介绍完了Python的多执行绪(Multi-Threading)-Thread套件的使用方法,大家是否已经跃跃欲试了,但受到GIL(Global Interpreter Lock)的限制,这样的方式在Python中执行速度不一定会比较快,所以下一次我会带大家跟我一起学习多进程Multi-Processing的使用方法喔~~


Reference

https://blog.gtwang.org/programming/python-threading-multithreaded-programming-tutorial/

https://mofanpy.com/tutorials/python-basic/threading/

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!

為自己CodingYO~~ 剛跨入AI人工智慧領域的小小工程師, 熱愛自學, 熱愛分享, 下班後的我想為自己Coding, 積極撰寫教學文, 想將自學的程式知識分享給大家, 不斷追求進步的自己, 希望有一天能回饋社會,幫助需要幫助的人, 如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~ IG: https://www.instagram.com/coding_4_me/
  • 来自作者
  • 相关推荐

[Takeaways]原力效應 — Part1

[行銷5.0] 人工智慧的緣起

[Aptos學習筆記#8]Move進階使用 - Resource介紹一