进程是资源分配单位,系统会分配内存,屏幕,窗口。
线程是进程中真正执行的东西。
python中的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用。
1、多线程执行
#coding=utf-8 import threading import time def saySorry(): print("亲爱的,我错了,我能吃饭了吗?") time.sleep(1) if __name__ == "__main__": for i in range(5): t = threading.Thread(target=saySorry) t.start() #启动线程,即让线程开始执行2、自定义线程类
#coding=utf-8 import threading import time class MyThread(threading.Thread): def __init__(self, name1, age): super(MyThread, self).__init__() self.name1 = name1 self.age = age 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()
python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。
多线程之间共享全局变量,优点是方便在多个线程之间共享数据,缺点是线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)。
如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确:
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)测试结果: ---线程创建之前g_num is 0--- ----in work1, g_num is 1088005--- ----in work2, g_num is 1286202--- 2个线程对同一个全局变量操作之后的最终结果是:1286202
同步:
同步就是协同步调,按预定的先后次序进行运行
互斥锁:
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
写法:
# 创建锁 mutex = threading.Lock() # 锁定 mutex.acquire() # 释放 mutex.release()
锁的好处:
确保了某段关键代码只能由一个线程从头到尾完整地执行
锁的坏处:
阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁
死锁解决办法(
看门狗思想:过一一段时间就执行一次特殊的某行代码,如果长时间不执行,系统就自动重启
2.银行家算法
互斥锁:线程能够同步保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。某个线程要更改共享数据时,先将其锁定,此时资源的状态为锁定状态,其他线程不能更改,直到该线程释放资源。
当创建一个线程之后,函数里面所有的内存空间是这个线程独有的,在创建一个时,会重新创建一个内存空间。各人是各人的。函数里面的代码各人是各人的,不会共享。
非全局变量不需要加锁。
死锁:在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源时,就会造成死锁。
同步:同步就是协调步调,按照预定的先后次序进行运行 三把锁一环扣一环
异步:不同步
生产者与消费者模式:
1。队列 :进程中的队列和线程中的队列不是一个概念。队列就是用来给生产者和消费者解耦的。
2。栈
fifo: frist in frist out =>Queue
filo: frist in last out =>
一个函数想得到另一个函数的值,要么return 返回值,要么通过全局变量。
1、使用全局字典的方法
2、ThreadLocal:不用传参数,用一个全局变量,能过完成线程里边的所有的数据的传递,不会因为多个线程对参数的修改对程序产生影响。