线程相关知识

1.线程

#进程是资源分配的最小单位   (包工头)
#线程是程序调度的最小单位 (工人)

#线程的缘起
资源分配需要分配内存空间,分配cpu:
分配的内存空间存放着临时要处理的数据等,比如要执行的代码,数据
而这些内存空间是有限的,不能无限分配
目前配置高的主机,5万个并发已是上限.线程概念应用而生.

#线程的特点
线程是比较轻量级,能干更多的活,一个进程中的所有线程资源是共享的.
一个进程至少有一个线程在工作

线程的缺陷

#线程可以并发,但是不能并行(同一个进程下的多个线程不能分开被多个cpu同时执行)
#原因:
python是解释型语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度
容易造成不同的cpu却反复执行同一个程序.所以加了一把锁叫GIL
全局解释器锁(Cpython解释器特有) GIL锁:同一时间,一个进程下的多个线程只能被一个cpu执行

#想要并行的解决办法:
(1)用多进程间接实现线程的并行
(2)换一个Pypy,Jpython解释器

#程序分为计算密集型和io密集型
对于计算密集型程序会过度依赖cpu,但网页,爬虫,OA办公,这种io密集型的程序里,python绰绰有余

1.1进程中可以包含多个线程

import os,random,time
from threading import Thread
from multiprocessing import Process

def func(num):
    time.sleep(random.uniform(0.1,1))
    print("子线程",num ,os.getpid())

for i in range(10):
    t = Thread(target=func,args=(i,))
    t.start()

  从上代码可以看出,主线程加子线程一共有11个线程!

1.2 并发多线程 和 多进程,谁的速度快  => 多线程

import os,random,time
from threading import Thread
from multiprocessing import Process

def func(num):
    print("子线程",num ,os.getpid())

if __name__ == '__main__':
    startime = time.perf_counter()
    lst = []

    for i in range(1000):
        t = Thread(target=func,args=(i,))
        t.start()
        lst.append(t)

    for i in lst:
        # print(i)
        i.join()

    endtime = time.perf_counter()
    print("多线程执行的时间:",endtime-startime) #  0.31189374899986433

    # 多进程的执行时间
    startime = time.perf_counter()
    lst = []
    for i in range(1000):
        p = Process(target=func,args=(i,))
        p.start()
        lst.append(p)

    for i in lst:
        i.join()

    endtime = time.perf_counter()
    print("多进程执行的时间:",endtime-startime) # 多进程执行的时间: 2.034676988994761

1.3多线程共享同一份进程资源

import os,random,time
from threading import Thread
from multiprocessing import Process

num = 100
lst = []
def func():
    # 异步并发程序
    time.sleep(1)
    global num
    num -= 1

for i in range(100):
    t = Thread(target=func)
    t.start()
    lst.append(t)

for i in lst:
    i.join()

print(num)

  注意:线程与线程之前是异步并发的

1.4 线程相关的函数

  线程.is_alive() 检测线程是否仍然存在
  线程.setName() 设置线程名字
  线程.getName() 获取线程名字
  1.currentThread().ident 查看线程id号
  2.enumerate() 返回目前正在运行的线程列表
  3.activeCount() 返回目前正在运行的线程数量

import os,random,time
from threading import Thread
from multiprocessing import Process

def func():
    # pass
    time.sleep(0.5)
t = Thread(target=func)

print(t) # <Thread(Thread-1, initial)>
t.start()
print(t.is_alive()) # True
print(t.getName()) # Thread-1
t.setName("producer_wang1号")
print(t.getName()) # producer_wang1号

# (2).enumerate()  放回目前正在运行的线程列表
from threading import enumerate
from threading import currentThread

def func():
    print("子进程:",currentThread().ident) # 查看线程id号
    time.sleep(0.5)

for i in range(10):
    t = Thread(target=func)
    t.start()

print(enumerate())
print(len(enumerate())) # 11

# (3).activeCount()  返回目前正在运行的线程数量 (了解)
from threading import activeCount
from threading import currentThread
def func():
    print("子进程:",currentThread().ident)
    time.sleep(0.5)

for i in range(10):
    t = Thread(target=func)
    t.start()

print(activeCount()) # 11

2.守护线程

   等待所有线程全部执行结束之后,再终止。守护所有线程。主程序默认等待所有的子线程

from threading import Thread
import time
def func1():
    while True:
        time.sleep(0.5)
        print("我是子线程func1函数")

def func2():
    print("func2 start...")
    time.sleep(3)
    print("func2 end ...")

t1 = Thread(target=func1)
# 设置守护线程,在start调用之前进行设置 setDaemon
t1.setDaemon(True)
t1.start()

t2 = Thread(target=func2)
t2.start()

print("我是主线程。。。")

3.线程锁lock

from threading import Thread,Lock
n = 0
def func1(lock):
    global n

    for i in range(10000):
        lock.acquire()
        # 写法一
        n -=1
        lock.release()
def func2(lock):
    global n
    for i in range(10000):
        # 写法二
        with lock:
            n += 1
if __name__ == '__main__':
    # 创建一把锁
    lock = Lock()
    lst = []
    for i in range(10):
        # 10个线程专门负责加1
        t1 = Thread(target=func1,args=(lock,))
        # 10个线程专门负责减1
        t2 = Thread(target=func2,args=(lock,))
        t1.start()
        t2.start()
        lst.append(t1)
        lst.append(t2)
    for i in lst:
        i.join()
    print("主进程执行结束。。。")
    print(n)

4.信号量 Semaphore

from threading import Semaphore,Thread
import time
def func(i,sem):
    with sem:
        print(i)
        time.sleep(10)

sem = Semaphore(6) # 批量上锁6把
for i in range(20):
    Thread(target=func,args=(i,sem)).start()
原文地址:https://www.cnblogs.com/youhongliang/p/11871924.html