1. 线程
一个进程可以包含多个线程,一条线程就是进程中一个单一顺序的控制流。一个进程中可以并发多个线程,每条线程执行不同的任务。
1.1 使用Thread创建线程
import threading
import time
def task():
for i in range(3):
time.sleep(1)
print(f"线程名:{threading.current_thread().name}")
if __name__ == "__main__":
print("主线程开始")
# 创建线程对象,放到ts中
ts = []
for i in range(5):
p = threading.Thread(target=task)
ts.append(p)
# 启动线程
for i in ts:
i.start()
# 等待
for i in ts:
i.join()
print("主线程结束")
Thread(group=None, target=None, name=None,
args=(), kwargs=None, *, daemon=None)
- group 保留
- target 表示一个可调用对象,经程启动时,run方法会调用此对象。
- name 线程名
- args, kwargs是传递给target函数的参数
:: 方法和Process类基本一样。
1.2 使用Thread子类创建线程
继承Thread类,重写run方法即可。
import threading
import time
class SubThread(threading.Thread):
# 重写
def run(self):
for i in range(3):
time.sleep(1)
print(f"线程名:{threading.current_thread().name}")
if __name__ == "__main__":
print("主线程开始")
# 创建线程对象,放到ts中
ts = []
for i in range(5):
p = SubThread()
ts.append(p)
# 启动线程
for i in ts:
i.start()
# 等待
for i in ts:
i.join()
print("主线程结束")
2. 线程之间通信
和进程不同,多个线程可以访问进程中定义的全局变量。即在一个进程中的所有线程共享全局变量。
2.1 互斥锁
由于多个线程共享全局变量,在同一时刻都可以修改它,造成混乱。
互斥锁:防止多个线程同时读取某一块内存区域。互斥锁为资源引入一个状态:锁定和非锁定。某个线程要修改共享数据时,先将其锁定,此时资源的状态为锁定,其它线程不能更改。该线程用完释放资源,将资源状态变成非锁定,其它线程才可以锁定资源进行修改。
互斥锁保证了每次只有一个线程可以进行写入操作,保证数据的正确性。
import time
from multiprocessing import Lock
from threading import Thread
# 100张票
n = 100
def task():
global n
# 上锁
lock.acquire()
n -= 1
time.sleep(0.1)
print(f"购票成功,还剩下{n}张")
# 解锁
lock.release()
if __name__ == '__main__':
# 创建一把锁
lock = Lock()
cache = []
# 创建20个线程来买票
for i in range(20):
t = Thread(target=task)
t.start()
for i in cache:
i.join()
如果不上锁就混乱了,sleep之后,n的结果全是80,因为那个时间段n的值已经是80了。
在使用互斥锁时,要避免死锁。一般有多个锁时会造成死锁,甲等乙放锁,乙等甲放锁,都不放卡住了。
2.2 用队列在线程间通信
与队列在进程间通信一样,但用的Queue是queue模块的,而不是multiprocessing模块中的Queue
import random
import time
from queue import Queue
from threading import Thread
class Producer(Thread):
def __init__(self, q):
Thread.__init__(self)
self.q = q
def run(self):
for i in range(5):
print(f"生产了{i}")
self.q.put(i)
time.sleep(random.random())
print("下班")
class Consumer(Thread):
def __init__(self, q):
Thread.__init__(self)
self.q = q
def run(self):
for i in range(5):
v = self.q.get()
print(f"消费了{i}")
self.q.put(i)
time.sleep(random.random())
if __name__ == '__main__':
q = Queue()
p1 = Producer(q)
p2 = Consumer(q)
p1.start()
p2.start()
标签:__,Thread,python,self,print,线程,进程,import
From: https://www.cnblogs.com/three-sheep/p/17438264.html