• 并发编程


    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 = n
    10     time.sleep(0.1)  # 100个线程 都拿到了100  所以就是 100个线程100-1
    11     n = temp - 1
    12     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=0
    10     for i in range(100000000):
    11         res*=i
    12 
    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 Process
    32 from threading import Thread
    33 import threading
    34 import os,time
    35 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时,才能被抢到acquire
    10 from threading import Thread,RLock
    11 import time
    12 
    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 in
    21 Thread-2 in
    22 Thread-3 in
    23 
    24 Thread-4 in
    25 
    26 
    27 Thread-6 in
    28 Thread-5 in
    29 Thread-7 in
    30 
    31 
    32 Thread-8 in
    33 Thread-9 in
    34 
    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,currentThread
    38 import time
    39 
    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=0
    48     while not event.is_set():
    49         if n == 3:
    50             print('%s try too many times' %currentThread().getName())
    51             return
    52         print('%s try %s' %(currentThread().getName(),n))
    53         event.wait(0.5)
    54         n+=1
    55 
    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 0
    73 Thread-2 try 0
    74 Thread-3 try 0
    75 Thread-4 is checking
    76 Thread-3 try 1
    77 Thread-2 try 1
    78 Thread-1 try 1
    79 Thread-3 try 2
    80 Thread-1 try 2
    81 Thread-2 try 2
    82 Thread-3 try too many times
    83 Thread-2 try too many times
    84 Thread-1 try too many times
    85 """
    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 Timer
    11 import random
    12 
    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 res
    30 
    31     def check(self):
    32         while True:
    33             code=input('请输入你的验证码>>: ').strip()
    34             if code.upper() == self.cache:
    35                 print('验证码输入正确')
    36                 self.t.cancel()
    37                 break
    38 
    39 obj=Code()
    40 obj.check()




  • 相关阅读:
    渗透学习——资料整理
    c语言——运算符、分支结构、循环结构
    c语言——字符串变量、函数
    总结Java开发者经常会犯的前十种错误
    项目开发遇到的问题及其解决.总结
    Java开发者写SQL时常犯的10个错误
    Java开发中常见的异常问题
    Java编程:常见问题汇总
    Exploded location overlaps an existing deployment解决办法
    Eclipse下svn的创建分支/合并/切换使用
  • 原文地址:https://www.cnblogs.com/alice-bj/p/8711527.html
Copyright © 2020-2023  润新知