多线程,多进程和携程(实战篇)

858 阅读4分钟

实战篇一

Python 并发、并行、同步和异步——学习笔记

概念解析

  • 串行:同一个时间段只干一件事

  • 并行:同一个时间段可以干多件事

  • 并发 V.S. 并行

    • 并发是指一个时间段内,有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行(单核切换运行)。
    • 并行是指任意时刻点上,有多个程序同时运行在多个CPU上,即每个CPU独立运行一个程序(多核同时运行)。
    • 并行的最大数量和CPU的数量是一致的。
  • 同步 V.S. 异步

    • 同步是指代码调用IO操作时,必须等待IO操作完成返回才调用的方式
    • 异步是指代码调用IO操作时,不必等待IO操作完成返回调用的方式
  • 多线程:交替执行,另一种意义上的串行 \Rightarrow 比进程的概念小,减少了进程切换过程中的消耗

  • 多进程:并行执行,真正意义上的并行 \Rightarrow 通过切换不同的进程来实现多任务的并行

  • 多进程 V.S. 多线程

    • 由于全局解释锁GIL的存在,Python的多线程无法利用多核优势,所以不适合计算密集型任务,适合IO密集型任务。
    • CPU密集型任务适合使用多进程
    • 进程切换代价要高于线程
    • 线程之间可以通过全局变量来进行通信,但是进程不行。进程之间的数据是完全隔离的。
  • threading类:

    threading.Lock():同步锁(互斥锁),解决数据安全问题

    threading.RLock():递归锁,解决线程死锁问题

    threading.Semaphore()信号量,最多允许同时有n个线程,超过信号量的线程会被堵塞,直到有线程的信号量被释放。

    threading.Event()事件,让不同的线程保持同步而不是独立的运行,彼此交互你给我发一个信号,我接到了执行一个操作,再给你发一个信号,你接到了执行操作并继续发信号……

import threading
#生成锁对象,全局唯一
lock = threading.Lock()
#获取锁
lock.acquire()
#释放锁
lock.release()
  • 可以使用上下文管理协议来管理锁
lock = threading.Lock()
with lock:
    pass
#等价于:
lock.acquire()
try:
    pass
finally:
    lock.release()
  • 加锁会影响性能,获取锁和释放锁都需要时间。
  • 使用锁可能会引起死锁

多线程

import threading
import time

def sleeper(n,name):
    print('Hi, I`m {}. I`m going to sleep 5 seconds'.format(name))
    time.sleep(n)
    print('{} has woken up from sleep'.format(name))
    
e.g.1
def main():
    t = threading.Thread(target = sleeper, args = (5,'thread1'))
    t.start()

    #调用.join()方法来阻塞当前线程,直到该线程结束后,才跳转执行其余的线程
    #t.join() 如果加上这个语句,程序需要等整个sleeper执行完毕后才会跳回执行后面的两次print

    print('hello')
    print('hello')
>>
Hi, I`m thread1. I`m going to sleep 5 seconds.
hello
hello
thread1 has woken up from sleep.

start和join正确的使用方式

# 这个是正确的使用方式
# 将start和join的方式进行分开循环
import threading
import time

def sleeper(n,name):
    print('Hi, I`m {}. I`m going to sleep 5 seconds'.format(name))
    time.sleep(n)
    print('{} has woken up from sleep'.format(name))

e.g.2
def main():
    start = time.time()
    thread_list = []
    for i in range(1,6):
        t = threading.thread(target=sleeper, args=(5,'thread{}'.format(i)))
        thread_list.append(t)
        t.start()
        print('{} has started.'.format(t.name)
    
    # join的使用
    for t in thread_list:
        t.join()
    end = time.time()
    print('total time: {}'.format(end - start))
    print('aaa')  
              
>>
Hi, I`m thread1. I`m going to sleep 5 seconds
Thread-1 has started.
Hi, I`m thread2. I`m going to sleep 5 seconds
Thread-2 has started.
Hi, I`m thread3. I`m going to sleep 5 seconds
Thread-3 has started.
Hi, I`m thread4. I`m going to sleep 5 seconds
Thread-4 has started.
thread2 has woken up from sleep
thread1 has woken up from sleep
thread4 has woken up from sleep
thread3 has woken up from sleep
total time: 5.001285791397095
aaa              

start和join错误的使用方式

错误的原因:将start和join的方式进行放在一起,错误的根本的原因是:当我们的第一个线程thread1启动了之后,直接进入了join,主程序进入等待,要等待thread1运行结束之后才能完成主程序下面的运行,在次进入循环,此时thread2.start(),直接又进入thread2.join,主程序又要等thread2运行结束,在开始thread3,这样的话,我们的程序在逻辑上又变成单线程了,所以在thread.start()后面直接接join的方式是错误的方式
# 这个是错误的使用方式
import threading
import time

def sleeper(n,name):
    print('Hi, I`m {}. I`m going to sleep 5 seconds'.format(name))
    time.sleep(n)
    print('{} has woken up from sleep'.format(name))

e.g.3
def main():
    start = time.time()
    thread_list = []
    for i in range(1,6):
        t = threading.thread(target=sleeper, args=(5,'thread{}'.format(i)))
        thread_list.append(t)
        t.start()
        t.join() #阻塞进程
        print('{} has started.'.format(t.name)

    end = time.time()
    print('total time: {}'.format(end - start))
    print('aaa')  
              
>>
Hi, I`m thread1. I`m going to sleep 5 seconds
thread1 has woken up from sleep
Thread-1 has started.
Hi, I`m thread2. I`m going to sleep 5 seconds
thread2 has woken up from sleep
Thread-2 has started.
Hi, I`m thread3. I`m going to sleep 5 seconds
thread3 has woken up from sleep
Thread-3 has started.
Hi, I`m thread4. I`m going to sleep 5 seconds
thread4 has woken up from sleep
Thread-4 has started.
total time: 20.00114393234253
aaa