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('\033[32;1mConsumer %s has eat %s baozi...\033[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就不适用了,可以用其他语言。

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

posted @ 2018-09-10 19:03  o云淡风轻o  阅读(242)  评论(0编辑  收藏  举报