活动地址:CSDN21天学习挑战赛
操作系统轮流让各个任务交替执行,表面看为交替执行,但由于CPU执行速度极快,呈现出来的效果和同步执行一样。
注意:
·并发:任务数多于CPU核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不再执行,因为切换任务速度相当快,看上去一起执行而已)。
·并行:任务数小于等于CPU核数,即任务真的是一起执行的。


使用Thread 创建线程方法:
1.为构造函数传递一个可调用对象
2.继承Thread类并在子类中重写 _init_()和 run()方法


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.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)



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)



- 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()

