python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装,可以更加方便的使用。
1、使用threading模块
多线程执行
#coding=utf-8
import time
def sey_sorry():
print("亲爱的,我错了,我能吃饭吗?")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
t = threaeding.Thread(target=say_sorry)
t.start()
多线程执行多个函数
#coding=utf-8
import time
import threading
def sing():
for i in range(5):
print("-------唱歌--------")
time.sleep(1)
def dance():
for i in range(5):
print("--------跳舞---------")
time.sleep(1)
def main():
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
if __name__ == "__main__":
main()
查看线程数量
#coding=utf-8
import time
import threading
def sing()
for i in range(5):
print("正在唱歌...")
time.sleep(1)
def dance():
for i in range(5):
print("正在跳舞...")
time.sleep(1)
if __name__ == "__main__":
print("------开始-----: %s"%(time.ctime(),))
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length = len(threading.enumerate())
print("当前运行线程数量: %s"%(length,))
if length <= 1:
break
time.sleep(0.5)
线程执行代码的封装
通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法。
#coding:=utf-8
import time
import threading
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+"@" +str(i)
print(msg)
self.login()
self.register()
def login(self):
pass
def register(self):
pass
if __name__ == "__main__":
t = MyThread()
t.start()
多线程-共享全局变量
#coding=utf-8
import time
from threading import Thread
g_num = 100
def work1():
global g_num
for i in range(3):
g_num += 1
print("----in work1, g_num is %d-----"%(g_num,))
def work2():
global g_num
print("---in work2, g_num is %d-----"%(g_num,))
print("-----线程创建之前g_num is %d----"%(g_num,))
t1= Threaed(target=work1)
t1.start()
time.sleep(1)
t2 = Thread(target=work2)
t2.satrt()
多线程传参
#coding=utf-8
import ime
import threading
def test1(temp):
temp.append(33)
print("----in test1 temp = %s----"%(str(temp),))
def test2(temp):
print("---in test2 temp = %s----"%(str(temp),))
g_nums = [11, 22]
def main():
# target 指定要执行的线程
# args 指定函数传递参数
t1 = threaeding.Thread(target=test1, args=(g_nums,))
t2 = threaeding.Thread(target=test2, args=(g_nums,))
t1.start()
time.slee(1)
t2.start()
time.sleep(1)
print("----in main Thread g_nums = %s----"%(g_nums,))
if __nam__ == "__main__":
main()
多线程-共享全局变量问题
假如两个线程t1和t2都要对全局变量g_num=0进行加1运算,t1和t2都各对g_num加10次,g_num的最终结果应该是20。
但是由于是多线程同时操作,有可能出现下面情况:
- 在g_num=0时,t1取得g_num=0。此时系统把t1调度为'sleeping'状态,把t2调度为'runing'状态。t2也获得g_num=0。
- 然后t2对得到的g_num进行加1并赋值给g_num,使得g_num=1。
- 然后系统有把t2调度为'sleeping',把t1转为'runing',此时t1又把之前得到的g_num=0进行加1赋值给g_num。
- 虽然t1和t2都对g_num加1,但是g_num最后的结果还是1。
这里就要加互斥锁来解决这个问题
# 创建锁
mutex = threading.Lock()
# 加锁
mutex.acquire()
# 解锁
mutex.release()
注意:
- 如果这个锁之前是没有上锁的,那么acquire不会阻塞
- 如果在调用acquire对这个锁上锁之前它已经被其他线程加锁了,那么此时acquire会阻塞,直到这个锁被解锁为止。
#coding=utf-8
# 使用互斥锁完成2个线程对同一个全局变量各加100万次
import time
import threading
g_num = 0
def test1(num):
global g_num
for i in range(num):
mutex.acquire() # 上锁
g_num += 1
mutex.release() # 解锁
print("----test1---g_num=%d"%(g_num,))
def test2(num):
global g_num
for i in range(num):
mutex.acquire() # 上锁
g_num += 1
mutex.release() # 解锁
print("----test2---g_num=%d"%(g_num,))
# 创建一个互斥锁
# 默认是未上锁状态
mutex = threading.Lock()
def main():
t1 = threading.Thread(target=test1, args=(1000000, ))
t2 = threading.Thread(target=test2, args=(1000000, ))
t1.start()
t2.start()
# 等待上面2个线程执行完毕...
time.sleep(2)
print("---in main Thread g_num = %d----"%(g_num,))
if __nam__ == "__main__":
main()
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
尽管死锁很少发生,一旦发生就会造成应用的停止响应。
#coding=utf-8
import time
import threaeding
class MyThreaed(threading.Thread):
def run(self):
# 对mutexA上锁
mutexA.acquire()
# mutexA上锁后,延迟1秒,等待另一个线程对mutexB上锁
print(self.name + "----do 1 -- up ---")
time.sleep(1)
# 此时会阻塞,因为这个mutexB已经被另外一个线程抢先上锁了
mutexB.acquire()
print(self.name+"----do1---down----")
mutexB.release()
# mutexA解锁
mutexA.release()
class MyThread2(threading.Thread):
def run(self):
# 对 mutexB上锁
mutexB.acquire()
# mutexB上锁后,延迟1秒,等待另外线程把mutexA上锁
print(self.name+"------do2-----up----")
time.sleep(1)
# 此时会阻塞,因为这个mutexA已经被另外线程上锁了
mutexA.acquirt()
print(self,name+"----do2------down------")
mutexA.release()
# mutexB解锁
mutexB.release()
mutexA = threading.Lock()
mutexB = threading.Lock()
if __name__ == "__main__":
t1 = MyThread1()
t2 = MyThread2()
t1.start()
t2.start()
网友评论