学习日志4—— 1.多任务活动地址:CSDN21天学习挑战赛
操作系统轮流让各个任务交替执行,表面看为交替执行,但由于CPU执行速度极快,呈现出来的效果和同步执行一样。
注意:
·并发:任务数多于CPU核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不再执行,因为切换任务速度相当快,看上去一起执行而已)。
·并行:任务数小于等于CPU核数,即任务真的是一起执行的。
2.threading模块 2.1常用方法—— 2.2Thread类使用说明——使用Thread 创建线程方法:
1.为构造函数传递一个可调用对象
2.继承Thread类并在子类中重写 _init_()和 run()方法
2.3线程对象 threading.Thread 的方法和属性 —— 2.4实例化 threading.Thread() ——2.4.1 单线程执行
#coding=utf-8
import threading
import time
def hearing():
print("干啥啥不行,躺平第一名")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
hearing()
2.4.2 使用threading模块
#coding=utf-8
import threading
import time
def hearing():
print("干啥啥不行,躺平第一名")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
t=threading.Thread(target=hearing)
t.start()#启动线程
多线程耗时更短,调用start()时,才会真正创建线程,并执行。
2.4.3 主线程会等待所有子线程结束后结束
#coding=utf-8
import threading
import time
from time import sleep,ctime
def hearing():
print("干啥啥不行,躺平第一名")
time.sleep(1)
def watching():
print("吃啥啥不剩,能吃是福")
time.sleep(1)
def saying():
print("我乐意")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
print("---开始---:%s"%ctime())
t1=threading.Thread(target=hearing)
t2=threading.Thread(target=watching())
t3=threading.Thread(target=saying())
t1.start()#启动线程
t2.start()
t3.start()
sleep(2)
print("---结束---:%s"%ctime())
输出——
2.4.4 查看线程数量
#coding=utf-8
import threading
import time
from time import sleep,ctime
def hearing():
print("干啥啥不行,躺平第一名")
#time.sleep(1)
def watching():
print("吃啥啥不剩,能吃是福")
#time.sleep(1)
def saying():
print("我乐意")
#time.sleep(1)
if __name__ == "__main__":
for i in range(2):
print("---开始---:%s"%ctime())
t1=threading.Thread(target=hearing)
t2=threading.Thread(target=watching())
t3=threading.Thread(target=saying())
t1.start()#启动线程
t2.start()
t3.start()
while True:
length=len(threading.enumerate())
print("当前运行线程数量:%d"%length)
if length<=1:
break
#sleep(1)
print("---结束---:%s"%ctime())
运行结果——
2.5 继承 threading.Thread2.5.1 线程执行代码的封装
#coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+' @ '+str(i) #name属性中保存的是当前线程的名字
print(msg)
if __name__ == '__main__':
t = MyThread()
t.start()
2.5.2 线程执行顺序
#coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+' @ '+str(i)
print(msg)
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
运行结果——
2.5.3 多线程-共享全局变量
from threading import Thread
import time
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 = Thread(target=work1)
t1.start()
#延时一会,保证t1线程中的事情做完
time.sleep(1)
t2 = Thread(target=work2)
t2.start()
运行结果——
2.5.4列表当作实参传递到线程中
from threading import Thread
import time
def work1(nums):
nums.append(44)
print("----in work1---",nums)
def work2(nums):
#延时一会,保证t1线程中的事情做完
time.sleep(1)
print("----in work2---",nums)
g_nums = [11,22,33]
t1 = Thread(target=work1, args=(g_nums,))
t1.start()
t2 = Thread(target=work2, args=(g_nums,))
t2.start()
2.5.5 多线程-全局变量问题
test1:
import threading
import time
g_num = 0
def work1(num):
global g_num
for i in range(num):
g_num += 1
print("----in work1, g_num is %d---"%g_num)
def work2(num):
global g_num
for i in range(num):
g_num += 1
print("----in work2, g_num is %d---"%g_num)
print("---线程创建之前g_num is %d---"%g_num)
t1 = threading.Thread(target=work1, args=(100,))
t1.start()
t2 = threading.Thread(target=work2, args=(100,))
t2.start()
while len(threading.enumerate()) != 1:
time.sleep(1)
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
结果
test2:
import threading
import time
g_num = 0
def work1(num):
global g_num
for i in range(num):
g_num += 1
print("----in work1, g_num is %d---"%g_num)
def work2(num):
global g_num
for i in range(num):
g_num += 1
print("----in work2, g_num is %d---"%g_num)
print("---线程创建之前g_num is %d---"%g_num)
t1 = threading.Thread(target=work1, args=(1000000,))
t1.start()
t2 = threading.Thread(target=work2, args=(1000000,))
t2.start()
while len(threading.enumerate()) != 1:
time.sleep(1)
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
3.线程同步
4.互斥锁
threading模块中定义了Lock类,可以方便的处理锁定
# 创建锁 mutex = threading.Lock() # 锁定 mutex.acquire() # 释放 mutex.release()
使用互斥锁完成2个线程对同一个全局变量各加100万次的操作
import threading
import time
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()
# 创建2个线程,让他们各自对g_num加1000000次
p1 = threading.Thread(target=test1, args=(1000000,))
p1.start()
p2 = threading.Thread(target=test2, args=(1000000,))
p2.start()
# 等待计算完成
while len(threading.enumerate()) != 1:
time.sleep(1)
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
5.死锁
import threading
import time
class MyThread1(threading.Thread):
def run(self):
# 对mutexA上锁
mutexA.acquire()
# mutexA上锁后,延时1秒,等待另外那个线程 把mutexB上锁
print(self.name+'----do1---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.acquire()
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()



