• python之网络编程--锁、信号量、线程、队列


    一、线程,可以发现顺序执行比开线程执行时间要短。原因是,一个进程中的多线程处理,由于存在GIL,并且GIL中只能存在一个线程,加上线程又存在切换的问题,所以时间耗得多。想要解决这个问题,是开几个进程,每个进程一个线程,就可以将cpu的多核利用起来,从而节省时间,不过进程对电脑消耗大,不建议开很多进程,因此可以用其他语言,Python不推荐

    def add():
        sum=0
    
        for i in range(10000000):
            sum+=i
        print("sum",sum)
    
    def mul():
        sum2=1
        for i in range(1,100000):
            sum2*=i
        print("sum2",sum2)
    
    import threading,time
    
    
    start=time.time()
    
    t1=threading.Thread(target=add)
    t2=threading.Thread(target=mul)
    
    l=[]
    l.append(t1)
    l.append(t2)
    
    
    # for t in l:
    #     t.start()
    #
    #
    #
    # for t in l:
    #     t.join()
    
    add()
    mul()
    
    print("cost time %s"%(time.time()-start))
    View Code

    二、关于线程间执行顺序的例子,由于线程是并发的,执行速度很快,如果不sleep的话,可能很快就执行完了,答案是0,但是如果在中间休眠0.001s,会发现结果就不正常了,这是因为在上一个进程还没有计算完的时候,下一个进程就已经取得了数据,解决这个问题,可以用锁,只有锁内的代码执行完后才会执行其他内容。

    import threading
    import time
    def sub():
        global num
       # num-=1
       #  print ("ok")
       #  lock.acquire()
        temp=num
        time.sleep(0.00001)
        num=temp-1
        # lock.release()
    
    num=100
    
    l=[]
    # lock=threading.Lock()
    
    for i in range(100):
        t=threading.Thread(target=sub)
        t.start()
        l.append(t)
    
    for t in l:
        t.join()
    
    print(num)
    View Code

     三、队列,put_nowait()相当于put(block=False),q = queue.Queue(3)里面的参数3代表,队列的大小为3个,其余的放不进去,必须等到队列里面有数被提出去了,才可以将数据放进来。

    # import threading,time
    #
    # li=[1,2,3,4]
    #
    #
    # def pri():
    #     while li:
    #         a=li[-1]
    #         print(a)
    #         time.sleep(1)
    #         li.remove(a)
    #         # try:
    #         #     li.remove(a)
    #         # except Exception as e:
    #         #     print('----',a,e)
    #
    # t1=threading.Thread(target=pri,args=())
    # t1.start()
    # t2=threading.Thread(target=pri,args=())
    # t2.start()
    
    
    
    import queue      #  线程 队列
    
    q=queue.Queue(3)  # FIFO模式
    
    q.put(12)
    q.put("hello")
    q.put({"name":"yuan"})
    q.put_nowait(56)#  q.put(block=False)
    
    print(q.qsize())
    print(q.empty())
    print(q.full())
    # q.put(34,False)
    
    
    while 1:
        data=q.get()
        print(data)
        print("----------")
    
    
    
    #先进后出
    # import queue
    
    # q=queue.LifoQueue()
    #
    # q.put(12)
    # q.put("hello")
    # q.put({"name":"yuan"})
    #
    # while 1:
    #     data=q.get()
    #     print(data)
    #     print("----------")
    
    # q=queue.PriorityQueue()
    #
    # q.put([3,12])
    # q.put([2,"hello"])
    # q.put([4,{"name":"yuan"}])
    #
    # while 1:
    #     data=q.get()
    #     print(data[1])
    #     print("----------")
    View Code

    四、线程中setDamon()运用,主线程退出,子线程也退出。

    import threading
    
    
    # def foo():
    #     print("ok")
    #
    #
    # t1=threading.Thread(target=foo)
    # t1.start()
    #
    # print("ending...")
    
    
    
    # class MyThread(threading.Thread):
    #
    #     def run(self):
    #         print("ok")
    #
    #
    # t1=MyThread()
    # t1.start()
    # print('ending')
    
    
    import threading
    from time import ctime,sleep
    import time
    
    def ListenMusic(name):
    
            print ("Begin listening to %s. %s" %(name,ctime()))
            sleep(2)#  sleep等同于IO操作
            print("end listening %s"%ctime())
    
    def RecordBlog(title):
    
            print ("Begin recording the %s! %s" %(title,ctime()))
            sleep(5)
            print('end recording %s'%ctime())
    
    
    threads = []
    
    
    t1 = threading.Thread(target=ListenMusic,args=('水手',))
    t2 = threading.Thread(target=RecordBlog,args=('python线程',))
    
    threads.append(t1)
    threads.append(t2)
    
    if __name__ == '__main__':
        #t1.setDaemon(True)
        t2.setDaemon(True)
        for t in threads:
            #t.setDaemon(True) #注意:一定在start之前设置
            t.start()
            # t.join()
    
        #t1.join()
        #t1.setDaemon(True)
    
        #t2.join()########考虑这三种join位置下的结果?
        print ("all over %s" %ctime())
    View Code

    五、递归锁,用递归锁,解决死锁问题。

    import  threading
    import time
    
    
    class MyThread(threading.Thread):
    
        def actionA(self):
    
            r_lcok.acquire() #count=1
            print(self.name,"gotA",time.ctime())
            time.sleep(2)
            r_lcok.acquire() #count=2
    
            print(self.name, "gotB", time.ctime())
            time.sleep(1)
    
            r_lcok.release() #count=1
            r_lcok.release() #count=0
    
    
        def actionB(self):
    
            r_lcok.acquire()
            print(self.name, "gotB", time.ctime())
            time.sleep(2)
    
            r_lcok.acquire()
            print(self.name, "gotA", time.ctime())
            time.sleep(1)
    
            r_lcok.release()
            r_lcok.release()
    
    
        def run(self):
    
            self.actionA()
            self.actionB()
    
    
    if __name__ == '__main__':
    
        # A=threading.Lock()
        # B=threading.Lock()
    
        r_lcok=threading.RLock()
        L=[]
    
        for i in range(5):
            t=MyThread()
            t.start()
            L.append(t)
    
    
        for i in L:
            i.join()
    
        print("ending....")
    View Code

    六、生产者消费者模型

    import time,random
    import queue,threading
    
    q = queue.Queue()
    
    def Producer(name):
      count = 0
      while count <10:
        print("making........")
        time.sleep(5)
        q.put(count)
        print('Producer %s has produced %s baozi..' %(name, count))
        count +=1
        #q.task_done()
        q.join()
        print("ok......")
    
    def Consumer(name):
      count = 0
      while count <10:
            time.sleep(random.randrange(4))
        # if not q.empty():
        #     print("waiting.....")
            #q.join()
            data = q.get()
            print("eating....")
            time.sleep(4)
    
            q.task_done()
            #print(data)
            print('33[32;1mConsumer %s has eat %s baozi...33[0m' %(name, data))
        # else:
        #     print("-----no baozi anymore----")
            count +=1
    
    p1 = threading.Thread(target=Producer, args=('A君',))
    c1 = threading.Thread(target=Consumer, args=('B君',))
    c2 = threading.Thread(target=Consumer, args=('C君',))
    c3 = threading.Thread(target=Consumer, args=('D君',))
    
    p1.start()
    c1.start()
    c2.start()
    c3.start()
    View Code

    七、同步对象,event的使用

    import threading,time
    class Boss(threading.Thread):
    
        def run(self):
            print("BOSS:今晚大家都要加班到22:00。")
            print(event.isSet())# False
            event.set()
            time.sleep(5)
            print("BOSS:<22:00>可以下班了。")
            print(event.isSet())
            event.set()
    
    class Worker(threading.Thread):
        def run(self):
    
            event.wait()#    一旦event被设定,等同于pass
    
            print("Worker:哎……命苦啊!")
            time.sleep(1)
            event.clear()
            event.wait()
            print("Worker:OhYeah!")
    
    
    if __name__=="__main__":
        event=threading.Event()
    
    
        threads=[]
        for i in range(5):
            threads.append(Worker())
        threads.append(Boss())
        for t in threads:
            t.start()
        for t in threads:
            t.join()
    
        print("ending.....")
    View Code

    八、semaphore的使用,限定同时运行线程的个数

    import threading,time
    
    
    class myThread(threading.Thread):
        def run(self):
    
            if semaphore.acquire():
                print(self.name)
                time.sleep(3)
                semaphore.release()
    
    if __name__=="__main__":
        semaphore=threading.Semaphore(3)
    
        thrs=[]
        for i in range(100):
            thrs.append(myThread())
        for t in thrs:
            t.start()
    View Code

    九、进程调用

    # from multiprocessing import Process
    # import time
    #
    #
    # def f(name):
    #     time.sleep(1)
    #     print('hello', name,time.ctime())
    #
    # if __name__ == '__main__':
    #     p_list=[]
    #     for i in range(3):
    #
    #         p = Process(target=f, args=('alvin',))
    #         p_list.append(p)
    #         p.start()
    #
    #     for i in p_list:
    #         i.join()
    #     print('end')
    
    
    from multiprocessing import Process
    import time
    
    # class MyProcess(Process):
    #
    #     # def __init__(self):
    #     #     super(MyProcess, self).__init__()
    #     #     #self.name = name
    #
    #     def run(self):
    #         time.sleep(1)
    #         print ('hello', self.name,time.ctime())
    #
    #
    # if __name__ == '__main__':
    #     p_list=[]
    #
    #
    #     for i in range(3):
    #         p = MyProcess()
    #         p.daemon=True
    #         p.start()
    #         p_list.append(p)
    #
    #     # for p in p_list:
    #     #     p.join()
    #
    #     print('end')
    
    
    from multiprocessing import Process
    import os
    import time
    
    
    def info(title):
        print("title:", title)
        print('parent process:', os.getppid())
        print('process id:', os.getpid())
    
    def f(name):
    
        info('function f')
        print('hello', name)
    
    
    if __name__ == '__main__':
    
        info('main process line')
    
        time.sleep(1)
        print("------------------")
        p = Process(target=info, args=('yuan',))
        p.start()
        p.join()
    View Code

    笔记:

    1.同步锁
    2.死锁 递归锁
    3.信号量和同步对象(了解)
    4.队列------生产者消费者模型
    5.进程

    并发 & 并行
    并发:是指系统具有处理多个任务(动作)的能力
    并行:是指系统具有同时处理多个任务(动作)的能力
    并行是并发的一个子集
    几个线程是并发,因为有GIL,所以只能允许一个线程运行,是并发
    几个进程是并行,可以解决线程不能同时运行的问题。可以几个CPU共同运行


    同步 与 异步
    同步:当进程执行到一个IO(等待外部数据)的时候,-----等:同步
    异步: -----不等:异步
    打电话是同步,发短信是异步

    问题:多核没利用上?
    GIL:Global_interpreter_lock全局解释锁
    因为有GIL,所以同一时刻只有一个线程被CPU执行


    任务:IO密集型 计算密集型

    对于IO密集型的任务:python的多线程是有意义的
    可以采用多进程+携程
    对于计算密集型的任务:python的多线程就不推荐,python就不适用了,可以用其他语言。

    信号量用来控制线程并发数的。

  • 相关阅读:
    PHP-xml-1
    BZOJ 1833 ZJOI2010 count 数字计数 数位DP
    运算符总结
    大写和小写转换
    Java基础:泛型
    Codeforces Round #156 (Div. 2)---A. Greg&#39;s Workout
    【Git】GitHub for Windows使用(2) 分支
    【Git】GitHub for Windows使用(1)
    【java JVM】JVM中类的加载,加载class文件的原理机制
    【FTP】org.apache.commons.net.ftp.FTPClient实现复杂的上传下载,操作目录,处理编码
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/9621902.html
Copyright © 2020-2023  润新知