day38

一、如何开启线程

进程是操作系统调度的最小单位,线程是cpu调度的最小单位。一个进程最少有一个主线程,一个进程中能开启多个线程。真正干活的是线程。

from multiprocessing import Process
from threading import Thread

def task():
    print("我是子线程")

if __name__ == '__main__':
    t = Thread(target=task, args=())
    t.start()

    print("主线程")

 

二、GIL全局解释锁

Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。

Python解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。

1、GIL锁它是在python解释器中的,只在cpython中有,pypy解释器是没有GIL锁的。

2、起一个垃圾回收线程,一个是正常执行的线程。

3、设置了一把锁(GIL锁),一个线程要执行,必须拿到这把锁

4、同一时刻,开启一个进程,一个进程中可以有多个线程,只能有一个线程在执行。

5、如果是计算密集型:要开进程(计算密集型是调用CPU的计算功能,相当于开多核,开多个进程能达到效果)

6、如果是io密集型:要开线程(IO密集型不涉及到计算,开线程也能达到要求,但相当于开线程,开进城占用的资源多,且起进程消耗也大于于开线程,速度也慢于开线程)

三、进程与线程的效率比较

import time

def task():
    time.sleep(1)
    print("我是主进程")

from multiprocessing import Process

if __name__ == '__main__':
    ctime = time.time()
    p = Process(target=task)
    p.start()
    p.join()
    print("主进程")
    print(time.time() - ctime)

import time

def task():
    time.sleep(1)
    print("我是主线程")

from threading import Thread

if __name__ == '__main__':
    ctime = time.time()
    p = Thread(target=task)
    p.start()
    p.join()
    print("主线程")
    print(time.time() - ctime)

四、线程之间的数据共享问题

from threading import Thread

# 线程之间的数据是共享的
def work():
    global n
    n=0

if __name__ == '__main__':

    n=1
    t=Thread(target=work)
    t.start()
    t.join()
    print('',n) # 查看结果为0,因为同一进程内的线程之间共享进程内的数据

五、Thread类的方法

1、Thread实例对象的方法:

  • is_alive():返回线程是否活动的。
  • getName():返回线程名。
  • setName():设置线程名。

threading模块提供的一些方法:

  • threading.currentThread():返回当前的线程变量。
  • threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

2、join方法

t.join():主线程等待t子线程终止,而不能join住run开启的进程

六、守护线程

主线程运行结束,整个进程结束(不管子进程是否结束,都会结束进程)。

from threading import Thread
import time
def task():
    time.sleep(1)
    print("我是子线程")

if __name__ == '__main__':
    t = Thread(target=task,)
    t.setDaemon(True)  # 开启守护线程,  主线程结束,子线程跟着结束
    t.start()

    print("主线程")

七、互斥锁(同步锁)

from threading import Thread, Lock
import time

def task(lock):
    # 上锁
    lock.acquire()
    global n

    temp = n
    # 并发安全
    # 10个线程都卡在这了
    time.sleep(1)
    # n -= 1  # n=n-1
    n = temp-1
    # 释放锁
    lock.release()

if __name__ == '__main__':
    n = 10
    ll = []
    lock = Lock()
    for i in range(10):
        t = Thread(target=task, args=(lock, ))
        t.start()
        ll.append(t)

    for j in ll:
        j.join()

    print("主线程:", n)

八、信号量

 

from threading import Thread,Semaphore
import time

def task(i, sm):
    # 上锁
    sm.acquire()
    print("%s:这个人开始上厕所了" % i)
    time.sleep(3)
    print("%s:这个人上完了" % i)
    # 释放锁
    sm.release()

# Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据
if __name__ == '__main__':
    sm = Semaphore(2)  #
    for i in range(10):
        t = Thread(target=task, args=(i, sm))
        t.start()

 

九、Event事件

from threading import Thread, Event
import time

def girl(event):
    print("都女士正在恋爱中...")
    time.sleep(3)
    print("都女生分手了")

    # 发出分手的信号
    event.set()

def boy(i, event):
    print("渣男:%s正在等待都女生分手" % i)
    # 卡住
    event.wait()
    print("渣男:%s开始追了" % i)

if __name__ == '__main__':
    event = Event()

    t = Thread(target=girl, args=(event,))
    t.start()

    for i in range(10):
        b_t = Thread(target=boy, args=(i, event))
        b_t.start()

 

posted @ 2021-07-22 20:35  Gnomeshghy  阅读(36)  评论(0)    收藏  举报