2018-07-30-Python全栈开发day34-锁、信号量、线程、队列-part1-线程

1.并发并行与同步异步的概念

  • 并发:指系统具有处理多个任务(动作)的能力
  • 并行:指系统具有同时处理多个任务(动作)的能力
  • 同步:进程在IO操作时进行等待
  • 异步:进程在IO操作时不等待,处理其他事情,IO操作完成再回来继续执行。

2.GIL概念

  GIL是python解释器在程序的每个进程上加了一把锁,在这个进程中, 同时只允许一个线程运行。

  在同一个进程内,不同的线程会竞争cpu的使用权。

  由于GIL的存在,理论上串行的效果比较好,但是遇到IO操作,计算密集型操作的时候,多线程处理速度较快

  2.1 解决方法

  •  开启不同的进程
  • 多进程+协程

pass:作为一个程序员,除了python之外,肯定还要掌握其他语言,只学习python肯定是不够的。

3.同步锁

  多个线程在对同一个数据进行处理时,可能导致重复对数据进行处理,不能得到及时反馈,所以给线程加一把锁,当某个线程在执行的时候,其他线程不能使用,等这个线程执行好数据之后再进行竞争。

  

import threading,time

num=100

def test():

    global num
    lock.acquire()#获取这把锁
    temp=num
    time.sleep(0.01)
    num=temp
    num -=1
    lock.release()#释放这把锁,在这个过程中

l=[]
lock=threading.Lock()
for  i in range(100):
    t=threading.Thread(target=test)
    t.start()
    l.append(t)
for x in l:
    x.join()#时间可能改变的原因:第一次循环进行时,在num的结果还没有计算出来时,第二次循环就开始了,导致第二次num拿到的值和第二次一样


print(num)
同步锁

当多个线程同时对一个全局变量进行处理时,在一个变量没有处理完是,比如说100-1,下一个线程已经开始运算,但是拿到的数据不是99,依旧是100,多个线程做了重复的无用工作,用同步锁将线程锁住,等这个线程执行完之后,其他的线程再执行,实质上是进行串行处理。

4.递归锁-死锁

  当两个线程,加了两把锁的时候,a线程加上a锁,b线程加上b锁,当a再去需要b锁,b需要a锁的时候,两个线程互相掰手腕,就形成了死锁

  

import threading, time


class Mythread(threading.Thread):
    def run(self):
        self.actionA()#运行a线程
        # time.sleep(8.1
        #            )
        self.actionB()#运行b线程

    def actionA(self):
        A.acquire()#获得一把a锁
        print(self.name, time.ctime())#打印时间
        time.sleep(2)#休眠两秒,此时其他线程正在等待a运行完

        B.acquire()#获得b锁
        print(self.name, time.ctime())
        time.sleep(2)
        B.release()
        A.release()#释放a和b锁,此时其他线程开始竞争,,线程a开始执行b动作

    def actionB(self):
        B.acquire()#在a线程获得b锁的同事,其他线程B获得a锁
        print(self.name, time.ctime())
        time.sleep(2)
        A.acquire()#a想要获得a锁的时候,b已经获得a锁,互不相让
        print(self.name, time.ctime())
        A.release()
        B.release()


if __name__ == '__main__':
    A = threading.Lock()
    B = threading.Lock()
    L = []
    for i in range(5):
        t = Mythread()
        t.start()
        L.append(t)
    for i in L:
        i.join()
死锁

5.同步对象event

  用于多线程之间进行沟通,只有是true的时候才继续运行

  •  event.wait==>false
  • event.set==>true
  • event.clear==>清空状态,false
import threading,time


class Mythreading(threading.Thread):
    def __init__(self):
        super(Mythreading,self).__init__()
    def run(self):
        print('this is run')
        time.sleep(2)
        print('this is wait')
        event.wait()
l=[]
event=threading.Event()
for i in range(4):
    l.append(Mythreading())
for s in l:
    s.start()#运行run方法
    # s.join()#如果是单个线程的话,没有线程来给他解决wait的问题
    print('准备开始激活')
    event.()#主线程激活的
event

6.信号量

  最多只能同时执行多少个线程

  相当于一个新的锁,锁住只能特定线程

import threading,time

class Myclass(threading.Thread):
    def run(self):
        if sema.acquire():
            print(self.name)
            time.sleep(3)
            sema.release()

if __name__ == '__main__':
    sema=threading.Semaphore(5)
    l=[]
    for i in range(100):
        l.append(Myclass())
    for s in l:
        s.start()
信号量

7.线程队列 queue

可以实现多个线程之间进行通讯

q=queue.Queue(4)#最多只能放入四个数据

q.put()====在队列中放入数据

q.get()===从队列中取出数据

q.put(5,false)===将5放入数据,如果数据满了直接报错

q.get(5,false)==同上

  7.1 queue队列的进出模式

  • 默认先进先出模式
  • 先进后出q=queue.LifoQueue
  • 优先级模式  q=queue.PriorityQueue
q=queue.PriorityQueue()
q.put(1,'546')#546的有些级别为1

  7.2 队列的方法

  •   q.size()==>队列的方法
  • q.empty()==>返回队列是否为空
  • q.ful()==>同上
  • q.get_nowait()==q.get(5,false)

  7.3 task_done,join

    一个task_done对应一个join,join的时候程序是阻塞的,当得到一个done的时候继续运行。、

  

# import queue
#
#
# # q=queue.Queue(5)#这个队列最多只能存储五个数据
# #
# # q.put('123')
# # q.put('alex')
# # # q.put(['alex'])
# # q=queue.PriorityQueue()
# # q.put(1,'546')#546的有些级别为1
# #
# # a=q.get()
# # b=q.get()
# # print(a)
# # print(b)
# import threading,time,queue
# class Myclass(threading.Thread):
#     def __init__(self,que):
#         threading.Thread.__init__(self)
#         self.que=que
#     def run(self):
#         while 1:
#             time.sleep(1)
#             if self.queue.empty():
#                 break
#             item=self.queue.get()
#             print(item,'11')
#         return
#
# q=queue.Queue()
#
# l=[]
# for i in range(2):
#     l.append(Myclass('que'))
#
# for x in range(10):
#
#     q.put(x)
#
# for m in l:
#     m.start()
# q.join()
#
import threading
import queue
from time import sleep

que = queue.Queue()


class Testthread(threading.Thread):
    def __init__(self, que):#继承线程父类
        threading.Thread.__init__(self)
        self.queue = que

    def run(self):#自定义run
        while True:
            sleep(1)
            item = self.queue.get()#从队列中拿数据
            print(item)
            # self.queue.task_done()#拿完之后done一下,这样别的线程就知道这个动作完成了


tasks = [Testthread(que) for x in range(2)]#连哥哥线程
for x in range(10):
    que.put(x)#在队列中放入是个数据,就是创建了一个队列,然后在队列中拿数据

for x in tasks:
    t = Testthread(que)#将这两个线程启动
    # t.setDaemon(True)
    t.start()


que.join()#之后阻塞
# print('这个是等待挂起')

print('all done')#如果内有taskdone,join后的程序将无法得到执行
task_done&join

  

  

猜你喜欢

转载自www.cnblogs.com/hai125698/p/9393543.html