博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
并发编程 - 线程 - 1.互斥锁/2.GIL解释器锁/3.死锁与递归锁/4.信号量/5.Event事件/6.定时器...
阅读量:5080 次
发布时间:2019-06-12

本文共 9398 字,大约阅读时间需要 31 分钟。

1.互斥锁:     原理:将并行变成串行     精髓:局部串行,只针对共享数据修改           保护不同的数据就应该用不用的锁
1 from threading import Thread, Lock 2 import time 3  4 n = 100 5  6 def task(): 7     global n 8     mutex.acquire()  # 效率低了 但是数据安全了 9     temp = n10     time.sleep(0.1)  # 100个线程 都拿到了100  所以就是 100个线程100-111     n = temp - 112     mutex.release()13 14 15 if __name__ == '__main__':16     mutex = Lock()17     t_l = []18     for i in range(100):19         t = Thread(target=task)20         t_l.append(t)21         t.start()22 23     for t in t_l:24         t.join()25 26     print('主', n)27 """28 主 99   原因: 100个线程 都拿到了100  所以就是 100个线程100-1  数据不安全 效率高但是不安全29           要将并行改为串行 30 """31 """32 主 0    原因:效率低了 但是数据安全了33 """

 

2.GIL: global interpreter lock     python3 test.py     ps aux | grep test     # linux     tasklist | findstr python   # windows  python.exe 运行python 会有几步:     1.会有一个进程,进程内存空间 python解释器的代码先加载到内存空间     2.test.py 内容加载到内存     3.解释执行;代码交给了python解释器         线程干活指向了python代码 python代码当作参数传给了解释器         线程拿到解释器的代码,拿着python代码当作参数,执行         垃圾回收线程运行解释器的代码         垃圾回收线程和某一个线程冲突了,数据不安全,

 

开多个进程,GIL就没影响了, cpython解释器垃圾回收线程定期启动一个     GIL:互斥锁,保证数据的安全 对CPython解释器,同一时间只有一个线程运行         GIL.acquire()  这样垃圾线程和线程就不会冲突了,这样回收机制就变得安全了         GIL.release()     python解释器,多线程有GIL存在,保证了一个进程下面多个线程的执行是一个一个执行的    有GIL与自动的锁的工作原理:

 

总结:         1.GIL 一个进程内的多个线程同一时间只能运行一个线程,垃圾回收线程是安全的         2.针对不同的数据,就应该加不同的锁,解释器级别的GIL锁,只能保护解释器级别的数据,           不能保护自己的数据,针对自己的共享数据还要加锁;           线程首先抢的是;GIL锁,之后才是mutex    官网:       结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势    GIL的存在:同一时刻,只能有一个线程在运行         多核,多进程,但进程开销大,多线程,又不能用多核 ?    cpu干计算的,多个cpu         1.如果是干计算的操作,多核省时间         2.如果干IO阻塞型操作,多核没用    程序运行:都会干计算和IO操作    四个任务:         1.1个核:开多线程  ,因为多进程能用上多核         2.多核:             计算密集型:用多进程,用多核,eg:金融行业的,计算比较多,虽然多进程开销大,但多核,保证了计算快             IO密集型:用多线程,同一时间只能用一个核,1个核一个进程,多线程就在一个核上来回切和四个核来回切是一样的    现在写的软件:       网络打交道,网络的IO       IO密集型,用多线程
1 """ 2 计算密集型应该用: 多进程 效率高   3 """ 4 from multiprocessing import Process 5 from threading import Thread 6 import os,time 7  8 def work(): 9     res=010     for i in range(100000000):11         res*=i12 13 14 if __name__ == '__main__':15     l=[]16     print(os.cpu_count()) #本机为8核17     start=time.time()18     for i in range(8):19         # p=Process(target=work) #耗时8s多20         p=Thread(target=work) #耗时37s多21         l.append(p)22         p.start()23     for p in l:24         p.join()25     stop=time.time()26     print('run time is %s' %(stop-start))27 28 """29 IO密集型:多线程 效率高30 """31 from multiprocessing import Process32 from threading import Thread33 import threading34 import os,time35 def work():36     time.sleep(2)37     print('===>')38 39 if __name__ == '__main__':40     l=[]41     print(os.cpu_count()) #本机为8核42     start=time.time()43     for i in range(400):44         # p=Process(target=work) #耗时8s多,大部分时间耗费在创建进程上45         p=Thread(target=work) #耗时2s多46         l.append(p)47         p.start()48     for p in l:49         p.join()50     stop=time.time()51     print('run time is %s' %(stop-start))

 

3.死锁:     你拿着我的锁,我拿着你的锁 互斥锁:Lock()     互斥锁只能acquire一次 递归锁:RLock()     可以连续acquire多次,每acquire一次计数器+1,     只有计数为0时,才能被抢到acquire
1 from threading import Thread,Lock 2 import time 3  4 mutexA=Lock() 5 mutexB=Lock() 6  7 class MyThread(Thread): 8     def run(self): 9         self.f1()10         self.f2()11 12     def f1(self):13         mutexA.acquire()14         print('%s 拿到了A锁' %self.name)15 16         mutexB.acquire()17         print('%s 拿到了B锁' %self.name)18         mutexB.release()19 20         mutexA.release()21 22 23     def f2(self):24         mutexB.acquire()25         print('%s 拿到了B锁' % self.name)26         time.sleep(0.1)27 28         mutexA.acquire()29         print('%s 拿到了A锁' % self.name)30         mutexA.release()31 32         mutexB.release()33 34 if __name__ == '__main__':35     for i in range(10):36         t=MyThread()37         t.start()38 """39 Thread-1 拿到了A锁  # 死锁了 卡住了40 Thread-1 拿到了B锁41 Thread-1 拿到了B锁42 Thread-2 拿到了A锁43 """
1 # 互斥锁只能acquire一次 2 # from threading import Thread,Lock 3 # 4 # mutexA=Lock() 5 # 6 # mutexA.acquire() 7 # mutexA.release() 8  9 # 递归锁:可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire10 from threading import Thread,RLock11 import time12 13 mutexB=mutexA=RLock()14 15 class MyThread(Thread):16     def run(self):17         self.f1()18         self.f2()19 20     def f1(self):21         mutexA.acquire()22         print('%s 拿到了A锁' %self.name)23 24         mutexB.acquire()25         print('%s 拿到了B锁' %self.name)26         mutexB.release()27 28         mutexA.release()29 30 31     def f2(self):32         mutexB.acquire()33         print('%s 拿到了B锁' % self.name)34         time.sleep(2)35 36         mutexA.acquire()37         print('%s 拿到了A锁' % self.name)38         mutexA.release()39 40         mutexB.release()41 42 if __name__ == '__main__':43     for i in range(10):44         t=MyThread()45         t.start()46 """47 Thread-1 拿到了A锁  # 解决了 死锁48 Thread-1 拿到了B锁49 Thread-1 拿到了B锁50 Thread-1 拿到了A锁51 Thread-2 拿到了A锁52 Thread-2 拿到了B锁53 Thread-2 拿到了B锁54 Thread-2 拿到了A锁55 Thread-4 拿到了A锁56 Thread-4 拿到了B锁57 Thread-5 拿到了A锁58 Thread-5 拿到了B锁59 Thread-5 拿到了B锁60 Thread-5 拿到了A锁61 Thread-7 拿到了A锁62 Thread-7 拿到了B锁63 Thread-7 拿到了B锁64 Thread-7 拿到了A锁65 Thread-9 拿到了A锁66 Thread-9 拿到了B锁67 Thread-9 拿到了B锁68 Thread-9 拿到了A锁69 Thread-3 拿到了A锁70 Thread-3 拿到了B锁71 Thread-3 拿到了B锁72 Thread-3 拿到了A锁73 Thread-6 拿到了A锁74 Thread-6 拿到了B锁75 Thread-6 拿到了B锁76 Thread-6 拿到了A锁77 Thread-10 拿到了A锁78 Thread-10 拿到了B锁79 Thread-10 拿到了B锁80 Thread-10 拿到了A锁81 Thread-8 拿到了A锁82 Thread-8 拿到了B锁83 Thread-8 拿到了B锁84 Thread-8 拿到了A锁85 Thread-4 拿到了B锁86 Thread-4 拿到了A锁87 """

 

4.信号量   信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,       信号量同一时间可以有5个任务拿到锁去执行       信号量:同一时间有多个线程在进行
1 from threading import Thread,Semaphore,currentThread 2 import time,random 3  4 sm=Semaphore(1) 5  6 def task(): 7     # sm.acquire() 8     # print('%s in' %currentThread().getName()) 9     # sm.release()10     with sm:  # 类似于sm.acquire() # 同一时间可以来3个人,1个人,或者2个人11         print('%s in' %currentThread().getName())12         time.sleep(random.randint(1,3))13 14 15 if __name__ == '__main__':16     for i in range(10):17         t=Thread(target=task)18         t.start()19 """20 Thread-1 in21 Thread-2 in22 Thread-3 in23 24 Thread-4 in25 26 27 Thread-6 in28 Thread-5 in29 Thread-7 in30 31 32 Thread-8 in33 Thread-9 in34 35 Thread-10 in 36 """

 

5.Event:    多个线程之间同步的,一个线程告诉另一些线程可以做其他的活了    event.wait()    event.wait(2)    event.set()    event.is_set()    event.clear()
1 from threading import Thread,Event 2 import time 3  4 event=Event() 5 # event.wait()   # 等 ...直到 set 6 # event.set() 7  8  9 def student(name):10     print('学生%s 正在听课' %name)11     # event.wait()  # 学生要等7秒 才能下课12     event.wait(2)   # 学生等2秒 直接下课了13 14     print('学生%s 课间活动' %name)15 16 17 def teacher(name):18     print('老师%s 正在授课' %name)19     time.sleep(7)20     event.set()21 22 23 if __name__ == '__main__':24     stu1=Thread(target=student,args=('alex',))25     stu2=Thread(target=student,args=('wxx',))26     stu3=Thread(target=student,args=('yxx',))27     t1=Thread(target=teacher,args=('egon',))28 29     stu1.start()30     stu2.start()31     stu3.start()32     t1.start()33 34 35 # ------------------36 # 设置链接的超时时间37 from threading import Thread,Event,currentThread38 import time39 40 event=Event()41 42 def conn():43     # print('%s is connecting'%currentThread().getName())44     # event.wait()45     # print('%s is connected'%currentThread().getName())46 47     n=048     while not event.is_set():49         if n == 3:50             print('%s try too many times' %currentThread().getName())51             return52         print('%s try %s' %(currentThread().getName(),n))53         event.wait(0.5)54         n+=155 56     print('%s is connected' %currentThread().getName())57 58 59 def check():60     print('%s is checking' %currentThread().getName())61     time.sleep(5)62     event.set()63 64 65 if __name__ == '__main__':66     for i in range(3):67         t=Thread(target=conn)68         t.start()69     t=Thread(target=check)70     t.start()71 """72 Thread-1 try 073 Thread-2 try 074 Thread-3 try 075 Thread-4 is checking76 Thread-3 try 177 Thread-2 try 178 Thread-1 try 179 Thread-3 try 280 Thread-1 try 281 Thread-2 try 282 Thread-3 try too many times83 Thread-2 try too many times84 Thread-1 try too many times85 """

 

6.定时器:Timer   t=Timer(5,task,args=('egon',))   t.start()   t.cancel()
1 from threading import Timer 2  3 def task(name): 4     print('hello %s' %name) 5  6 t=Timer(5,task,args=('egon',))  # 就是起了一个线程 7 t.start() 8  9 # ----------------------10 from threading import Timer11 import random12 13 class Code:14     def __init__(self):15         self.make_cache()16 17     def make_cache(self,interval=10):18         self.cache=self.make_code()19         print(self.cache)20         self.t=Timer(interval,self.make_cache)21         self.t.start()22 23     def make_code(self,n=4):24         res=''25         for i in range(n):26             s1=str(random.randint(0,9))27             s2=chr(random.randint(65,90))28             res+=random.choice([s1,s2])29         return res30 31     def check(self):32         while True:33             code=input('请输入你的验证码>>: ').strip()34             if code.upper() == self.cache:35                 print('验证码输入正确')36                 self.t.cancel()37                 break38 39 obj=Code()40 obj.check()

 

转载于:https://www.cnblogs.com/mumupa0824/p/9398135.html

你可能感兴趣的文章
Redis快速入门
查看>>
BootStrap---2.表格和按钮
查看>>
Linear Algebra lecture 2 note
查看>>
CRC计算模型
查看>>
Ajax之404,200等查询
查看>>
Aizu - 1378 Secret of Chocolate Poles (DP)
查看>>
csv HTTP简单表服务器
查看>>
OO设计的接口分隔原则
查看>>
数据库连接字符串大全 (转载)
查看>>
java类加载和对象初始化
查看>>
对于负载均衡的理解
查看>>
django简介
查看>>
window.event在IE和Firefox的异同
查看>>
常见的js算法面试题收集,es6实现
查看>>
IO流写出到本地 D盘demoIO.txt 文本中
查看>>
Windows10 下Apache服务器搭建
查看>>
HDU 5458 Stability
查看>>
左手坐标系和右手坐标系
查看>>
solr后台操作Documents之增删改查
查看>>
http://yusi123.com/
查看>>