day39
线程锁例子(线程锁)不加锁的情况from threading import Thread,Lock x = 0 mutex = Lock() def task(): global x for i in range(100000): x += 1 ''' ==》t1 的 x刚拿到0 保存状态 就被切了 ==》t2 的 x拿到0 进行+1 1 ==》t1 又获得运行了 x = 0 +1 1 思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1 因此产生数据安全的问题 ''' if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t3 = Thread(target=task) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print(x) #结果<=300000(注意只有当range数据较大时才会产生这个问题) 加锁的情况from threading import Thread,Lock x = 0 mutex = Lock() def task(): global x mutex.acquire() for i in range(100000): x += 1 mutex.release() if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t3 = Thread(target=task) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print(x) #300000 死锁介绍死锁的这个概念在很多地方都存在,大概介绍下是怎么产生的
python中在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。 例子(死锁)import threading import time lock_apple = threading.Lock() lock_banana = threading.Lock() class MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): self.fun1() self.fun2() def fun1(self): lock_apple.acquire() # 如果锁被占用,则阻塞在这里,等待锁的释放 print ("线程 %s,想拿: %s--%s" %(self.name,"苹果",time.ctime())) lock_banana.acquire() print ("线程 %s,"香蕉",time.ctime())) lock_banana.release() lock_apple.release() def fun2(self): lock_banana.acquire() print ("线程 %s,time.ctime())) time.sleep(0.1) lock_apple.acquire() print ("线程 %s,time.ctime())) lock_apple.release() lock_banana.release() if __name__ == "__main__": for i in range(0,10): #建立10个线程 my_thread = MyThread() #类继承法是python多线程的另外一种实现方式 my_thread.start() -----------------------------------我是一条分割线--------------------------------- 线程 Thread-1,想拿: 苹果--Sun Apr 28 12:21:06 2019 线程 Thread-1,想拿: 香蕉--Sun Apr 28 12:21:06 2019 线程 Thread-1,想拿: 香蕉--Sun Apr 28 12:21:06 2019 线程 Thread-2,想拿: 苹果--Sun Apr 28 12:21:06 2019 上面的代码其实就是描述了苹果和香蕉的故事。大家可以仔细看看过程。下面我们看看执行流程
上面就是大概的执行流程和死锁出现的原因。在这种情况下就是在同一线程中多次请求同一资源时候出现的问题。 递归锁(RLock)介绍
例子(递归锁)下面我们用递归锁RLock解决上面的死锁问题: import threading import time lock = threading.RLock() #递归锁 class MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): self.fun1() self.fun2() def fun1(self): lock.acquire() # 如果锁被占用,等待锁的释放 print (f"线程{self.name},想拿:'苹果'--{time.ctime()}" ) lock.acquire() print (f"线程{self.name},想拿: '香蕉'--{time.ctime()}" ) lock.release() lock.release() def fun2(self): lock.acquire() print (f"线程{self.name},想拿: '香蕉'--{time.ctime()}" ) time.sleep(0.1) lock.acquire() print (f"线程{self.name},想拿:'苹果'--{time.ctime()}" ) lock.release() lock.release() if __name__ == "__main__": for i in range(0,3): #建立10个线程 my_thread = MyThread() #类继承法是python多线程的另外一种实现方式 my_thread.start() 线程Thread-1,想拿:‘苹果‘--Wed Sep 18 17:01:30 2019 上面我们用一把递归锁,就解决了多个同步锁导致的死锁问题。大家可以把RLock理解为大锁中还有小锁,只有等到内部所有的小锁,都没有了,其他的线程才能进入这个公共资源。 思考如果我们都加锁也就是单线程了,那我们还要开多线程有什么用呢?
信号量(Semphare)介绍它控制同一时刻多个线程访问同一个资源的线程数
例子(信号量)from threading import Thread,currentThread,Semaphore import time def task(): sm.acquire() print(f'{currentThread().name} 在执行') time.sleep(3) sm.release() sm = Semaphore(4) for i in range(12): t = Thread(target=task) t.start() Thread-1 在执行 Thread-5 在执行 Thread-9 在执行 GIL(全局解释器锁)介绍问题一:为什么python在多线程中为什么不能实现真正的并行操作呢(即在多CPU中执行不同的线程)?
问题二:为什么要有GIL锁?
分析:我们有四个任务需要处理,处理方式肯定是要玩出并发的效果
例子(任务)io密集型'''采用多进程计时情况''' def work1(): x = 1+1 time.sleep(5) if __name__ == '__main__': t_list = [] start = time.time() for i in range(4): t = Process(target=work1) t_list.append(t) t.start() for t in t_list: t.join() end = time.time() print('多进程',end-start) 多进程 5.499674558639526 '''采用多线程计时情况''' def work1(): x = 1+1 time.sleep(5) if __name__ == '__main__': t_list = [] start = time.time() for i in range(4): t = Thread(target=work1) # t = Process(target=work1) t_list.append(t) t.start() for t in t_list: t.join() end = time.time() print('多线程',end-start) 多线程 5.004202604293823
计算密集型'''采用多进程计时情况''' def work1(): res=0 for i in range(100000000): #1+8个0 res*=i if __name__ == '__main__': t_list = [] start = time.time() for i in range(4): t = Process(target=work1) t_list.append(t) t.start() for t in t_list: t.join() end = time.time() print('多进程',end-start) 多进程 18.062480211257935 '''采用多线程计时情况''' def work1(): res=0 for i in range(100000000): res*=i if __name__ == '__main__': t_list = [] start = time.time() for i in range(4): t = Thread(target=work1) # t = Process(target=work1) t_list.append(t) t.start() for t in t_list: t.join() end = time.time() print('多线程',end-start) 多线程 33.27059483528137
总结
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |