python中有关多线程的操作方法。
threading库是python支持多线程编程的重要模块。
一种方法是直接使用threading中的Thread类创建对象。
另一种方法是继承Thread类并重写__init__()
和run()
方法。
阻塞当前线程,等待被调线程结束或超时后再执行当前线程,timeout单位是秒。
from threading import Thread
import time
def fun(x, y):
for i in range(x, y):
print(i, end=' ')
print()
time.sleep(10) #等待10秒
t1 = Thread(target=fun, args=(15, 20))
t1.start()
t1.join(5) #等待t1结束或等待5秒
t2 = Thread(target=fun, args=(5, 10))
t2.start()
测试线程是否处于运行状态。
from threading import Thread
import time
def fun():
time.sleep(10) #等待10秒
t1 = Thread(target=fun)
print('t1:',t1.isAlive()) #False
t1.start()
print('t1:',t1.isAlive()) #True
t1.join(5) #因超时而结束
print('t1:',t1.isAlive()) #True
t1.join() #等待t1结束
print('t1:',t1.isAlive()) #False
如某个子线程的daemon属性为False(默认情况),主线程结束时会检测该子线程是否结束并等待它结束后再退出。若为True,则该子线程不管有没有运行玩,都会随主线程一起结束。
import threading
import time
class mythread(threading.Thread):
def __init__(self, num, threadname):
threading.Thread.__init__(self,name=threadname)
self.num = num
def run(self):
time.sleep(self.num)
print(self.num)
t1 = mythread(1, 't1')
t2 = mythread(5, 't2')
t2.daemon = True
t2.setDaemon(False)
print(t1.daemon) #False
print(t2.daemon) #True
t1.start()
t2.start()
1会输出,但5不会输出。
import threading
import time
class mythread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global x
lock.acquire() #获取锁,如果成功则进入临界区
x += 1
time.sleep(0.5)
print(x)
lock.release() #释放锁,退出临界区
lock = threading.RLock()
tl = [] #用来存放多个进程
x = 0
for i in range(10000):
t = mythread()
tl.append(t)
for i in tl:
i.start()
如果没有这把读锁,那么x的值将会变得杂乱无章,出现“脏读”现象。
“死锁”现象:假设有两个线程和两把锁,只有两把锁都给同一个线程的时候这个线程才会运行。那么问题来了,当两个线程各自获得了其中的一把锁,这时它们都在等待另一把锁释放,这时就会出现死锁现象。
用经典的生产者和消费者问题演示。
import threading
from random import randint
import time
class Producer(threading.Thread):
def __init__(self, threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
global x
while True:
con.acquire() #获取锁
if len(x) == 10:
print('Producer is waiting')
con.wait() #共享列表已有10个元素,不再生产
else:
print('Producer:', end=' ')
x.append(randint(1,1000))
print(x)
time.sleep(1)
con.notify() #唤醒等待条件的线程
con.release() #释放锁
class Consumer(threading.Thread):
def __init__(self, threadname):
threading.Thread.__init__(self, name =threadname)
def run(self):
global x
while True:
con.acquire()
if not x:
print('Consumer is waiting')
con.wait() #共享列表没东西,暂停消费
else:
print(x.pop(0))
print(x)
time.sleep(1)
con.notify()
con.release()
con = threading.Condition()
x = []
p = Producer('Producer')
c = Consumer('Consumer')
p.start()
c.start()
p.join()
c.join()
notify()方法是从所有等待这个对象锁的线程中随机唤醒一个。
notify_all()方法能够唤醒所有正在等待这个对象锁的线程,唤醒的线程获得锁的概率是随机的,取决于cpu调度。
notify()或者notify_alll()方法并不是真正释放锁,必须等到release方法执行完才真正释放锁。