zoukankan      html  css  js  c++  java
  • 线程相关(二)

    一. TCP server端通过线程实现并发

    server端

     1 from threading import Thread
     2 import socket
     3 
     4 sk = socket.socket()
     5 sk.bind(('127.0.0.1',8080))
     6 sk.listen()
     7 
     8 
     9 def talk(conn):
    10     while True:
    11         try:
    12             data = conn.recv(1024)
    13             print(data.decode('utf-8'))
    14             conn.send(b'hello!')
    15         except ConnectionRestError as e:
    16             break
    17 while True:
    18     conn,addr = sk.accept()
    19     print(addr)
    20     t = Thread(target = talk,args = (conn,))
    21     t.start()

    二.GIL全局解释器锁

    是CPython中的解释器锁

    通过一个例子了解GIL锁的存在

     1 from threading import Thread
     2 import time
     3 n = 100
     4 
     5 def task():
     6     global n 
     7     tmp = n 
     8     time.sleep(3)
     9     n = tmp -1
    10   
    11 t_list = []
    12 for i in range(100):
    13     t = Thread(target = task)
    14     t.start()
    15     t_list.append(t)
    16 
    17 for t in t_list:
    18     t.join()
    19 
    20 print(n)

    在这种情况下 执行结果是99  因为这里有time.sleep(3) 这是IO操作,会阻塞,在此处线程会释放GIL锁,等待下一个线程来抢,因此直到最后一个线程抢到锁 才做最后的减1操作  因此最终的结果是99

    如果将此处的time.sleep(3)注释掉之后  执行结果则是0

    研究python 的多线程是否有用需要分情况讨论
    1.四个任务 计算密集型的
    单核情况下
    开线程比开进程更省资源
    所以开线程好
    多核情况下
    开进程 要10S多
    开线程 要40s多


    2.四个任务 IO密集型 会不停的阻塞 不停的切
    单核情况下
    开线程更节省资源
    多核情况下
    开线程更节省资源

    三.死锁

    下面有个死锁的例子

     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.func1()
    10         self.func2()
    11 
    12     def func1(self):
    13         mutexA.acquire()
    14         print('%s抢到了A锁'%self.name) #self.name 等价于 current_thread().name
    15         mutexB.acquire()
    16         print('%s抢到了B锁'%self.name)
    17         mutexB.release()
    18         print('%s释放了B锁'%self.name)
    19         mutexA.release()
    20         print('%s释放了A锁'%self.name)
    21 
    22     def func2(self):
    23         mutexB.acquire()
    24         print('%s抢到了B锁' % self.name)
    25         time.sleep(1)
    26         mutexA.acquire()
    27         print('%s抢到了A锁' % self.name)
    28         mutexA.release()
    29         print('%s释放了A锁' % self.name)
    30         mutexB.release()
    31         print('%s释放了B锁' % self.name)
    32 
    33 for i in range(10):
    34     t = MyThread()
    35     t.start()
    36 #结果:
    37 '''
    38 Thread-1抢到了A锁
    39 Thread-1抢到了B锁
    40 Thread-1释放了B锁
    41 Thread-1释放了A锁
    42 Thread-1抢到了B锁
    43 Thread-2抢到了A锁
    44 死锁现象出现了
    45 自己千万不要轻易处理锁的问题
    46 '''

    根据结果再推导一遍,首先线程一 抢到了A锁和B锁,然后释放B锁,现在的B锁没有人抢,因为A锁还在线程一身上没人能抢B锁,然后线程一将A锁释放,接着线程一执行func2方法抢到了B锁,而A锁在刚才释放的一瞬间被线程二抢走了,所以现在 线程一有B锁,线程二有A锁,之后线程一在func2方法中需要抢A锁,而线程二需要B锁,但是这两把锁再对方身上,所以这样就成了死锁现象。

    四.递归锁

    from threading import  Thread,RLock #递归锁  可以连续acquire
    import time
    '''
    RLock 可以被第一个抢到锁的人连续的acquire 和 release
    每acquire一次 锁身上的计数加1
    每release一次  锁身上的计数减1
    只要锁的计数不为0 其他人不能抢
    '''
    
    mutexA = mutexB = RLock()  #这是一把锁 同一把锁
    
    class MyThread(Thread):
        def run(self):
            self.func1()
            self.func2()
    
        def func1(self):
            mutexA.acquire()
            print('%s抢到了A锁'%self.name) #self.name 等价于 current_thread().name
            mutexB.acquire()
            print('%s抢到了B锁'%self.name)
            mutexB.release()
            print('%s释放了B锁'%self.name)
            mutexA.release()
            print('%s释放了A锁'%self.name)
    
        def func2(self):
            mutexB.acquire()
            print('%s抢到了B锁' % self.name)
            time.sleep(1)
            mutexA.acquire()
            print('%s抢到了A锁' % self.name)
            mutexA.release()
            print('%s释放了A锁' % self.name)
            mutexB.release()
            print('%s释放了B锁' % self.name)
    
    for i in range(10):
        t = MyThread()
        t.start()
    #结果:
    '''
    Thread-1抢到了A锁
    Thread-1抢到了B锁
    Thread-1释放了B锁
    Thread-1释放了A锁
    Thread-1抢到了B锁
    Thread-1抢到了A锁
    Thread-1释放了A锁
    Thread-1释放了B锁
    Thread-2抢到了A锁
    Thread-2抢到了B锁
    Thread-2释放了B锁
    Thread-2释放了A锁
    Thread-2抢到了B锁
    Thread-2抢到了A锁
    Thread-2释放了A锁
    Thread-2释放了B锁
    Thread-4抢到了A锁
    Thread-4抢到了B锁
    Thread-4释放了B锁
    Thread-4释放了A锁
    Thread-4抢到了B锁
    Thread-4抢到了A锁
    Thread-4释放了A锁
    Thread-4释放了B锁
    Thread-6抢到了A锁
    Thread-6抢到了B锁
    Thread-6释放了B锁
    Thread-6释放了A锁
    Thread-6抢到了B锁
    Thread-6抢到了A锁
    Thread-6释放了A锁
    Thread-6释放了B锁
    Thread-8抢到了A锁
    Thread-8抢到了B锁
    Thread-8释放了B锁
    Thread-8释放了A锁
    Thread-8抢到了B锁
    Thread-8抢到了A锁
    Thread-8释放了A锁
    Thread-8释放了B锁
    Thread-10抢到了A锁
    Thread-10抢到了B锁
    Thread-10释放了B锁
    Thread-10释放了A锁
    Thread-10抢到了B锁
    Thread-10抢到了A锁
    Thread-10释放了A锁
    Thread-10释放了B锁
    Thread-5抢到了A锁
    Thread-5抢到了B锁
    Thread-5释放了B锁
    Thread-5释放了A锁
    Thread-5抢到了B锁
    Thread-5抢到了A锁
    Thread-5释放了A锁
    Thread-5释放了B锁
    Thread-9抢到了A锁
    Thread-9抢到了B锁
    Thread-9释放了B锁
    Thread-9释放了A锁
    Thread-9抢到了B锁
    Thread-9抢到了A锁
    Thread-9释放了A锁
    Thread-9释放了B锁
    Thread-7抢到了A锁
    Thread-7抢到了B锁
    Thread-7释放了B锁
    Thread-7释放了A锁
    Thread-7抢到了B锁
    Thread-7抢到了A锁
    Thread-7释放了A锁
    Thread-7释放了B锁
    Thread-3抢到了A锁
    Thread-3抢到了B锁
    Thread-3释放了B锁
    Thread-3释放了A锁
    Thread-3抢到了B锁
    Thread-3抢到了A锁
    Thread-3释放了A锁
    Thread-3释放了B锁
    '''

    五.信号量

    信号量可能再不同的领域中,对应不同的知识点

    这里将信号量与互斥锁做个对比

    互斥锁 :一个坑位的厕所

    信号量:多个坑位的厕所

    例子

     1 rom threading import Semaphore,Thread
     2 import time
     3 sm = Semaphore(5) #造了一个含有5个坑位的公共厕所
     4 
     5 def task(name):
     6     sm.acquire()
     7     print('%s占了一个坑位'%name)
     8     time.sleep(1)
     9     sm.release()
    10 
    11 
    12 for i in range(40):
    13     t = Thread(target=task,args=(i,))
    14     t.start()

    六.event事件

    from threading import Event,Thread
    import time
    #先生成一个event对象
    e = Event()
    
    def light():
        print('红灯亮..')
        time.sleep(3)
        e.set() #发信号
        print('绿灯亮..')
    
    def car(name):
        print('%s正在等红灯..'%name)
        e.wait() #等待信号
        print('%s加油门飙车'%name)
    
    t = Thread(target=light)
    t.start()
    for i in range(3):
        t = Thread(target=car,args=('伞兵%s'%i,))
        t.start()4
    #执行结果
    红灯亮..
    伞兵0正在等红灯..
    伞兵1正在等红灯..
    伞兵2正在等红灯..
    绿灯亮..
    伞兵0加油门飙车
    伞兵1加油门飙车
    伞兵2加油门飙车

    七.线程q

    同一个进程下的多个线程本来就是数据共享的

    为什么还用队列呢?

    因为队列是 管道+锁

    使用队列就不需要自己手动操作锁的问题

    因为锁操作的不好极容易产生死锁现象

    三个常见的:

    1.

    1 import queue
    2 q = queue.Queue()
    3 q.put('haha')
    4 print(q.get())

    2.

    import queue
    q = queue.LifoQueue()  #后进先出
    q.put(1)
    q.put(2)
    q.put(3)
    
    print(q.get())

    3.

    import queue
    q = queue.PriorityQueue()
    #数字越小 优先级越高
    q.put((10,'haha'))
    q.put((-10,'h3h3'))
    q.put((0,'xxx'))
    
    print(q.get())
    print(q.get())
    万般皆下品,唯有读书高!
  • 相关阅读:
    Android框架之Volley与Glide
    美团点餐—listview内部按钮点击事件
    Android之MaterialDesign应用技术2-仿支付宝上滑搜索框缓慢消失
    Android之MaterialDesign应用技术
    Android之Bmob移动后端云服务器
    Java设计模式总汇二---MVC、中介者设计模式
    Java设计模式总汇一 (适配器、单例、静态代理、简单工厂设计模式)
    Android数据绑定技术二,企业级开发
    再次强调完成的定义(DoD)
    在远程 CSM 课程中体验线上工作坊
  • 原文地址:https://www.cnblogs.com/s686zhou/p/11357062.html
Copyright © 2011-2022 走看看