几大锁

一    在python里边  列表 字典 队列等都是线程安全的                                                                  ,

# v = []   默认列表是安全的不用加锁
# def func(arg):
#     v.append(arg)  # 线程安全  在一个线程来添加的同时,不会有别的线程来捣乱,
#一个线程添加完毕,别的线程才会紧接着添加
# print(v) # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start()

二  Lock和Rlock                                                                                                                

Lock  几乎不用,不能重复获得锁,不能重复解锁.一旦这样做的话,会形成死锁.

Rlock    可以做到上面的重复获得锁,重复解锁

import threading,time


a = []
def fun(arg):

    a.append(arg)   这句代码本身是安全的,
    time.sleep(0.1)  后面这又要取出列表中的最后一个值,等待一秒之后
#这就线程不安全了.此时10个数都已经被添加进列表,最后取出的当然都是9
print(a[-1])
for i in range(10): t = threading.Thread(target=fun,args=(i,)) t.start() 结果 9 9 9 9 9 9 9 9 9 9 9 9

     下面加一把锁,试试看

import threading,time

lock = threading.RLock()    #赋值给一个变量用着简单
a = []
def fun(arg):
  #lock.acquire() #即使加上两把锁,只要后面解两下就和加一次锁解一次锁是一样的 lock.acquire() a.append(arg) time.sleep(
0.1) print(a[-1]) lock.release()
# lock.release()
for i in range(10): t = threading.Thread(target=fun,args=(i,)) t.start()
结果是 o 1 2 3 4 5 6 7 8 9

semaphore 锁

import  time ,threading

lock = threading.BoundedSemaphore(2)   #里面的参数是一次性最多放行2 个线程

def func(arg):

    lock.acquire()
    na = threading.get_ident()
    time.sleep(2)
    print(arg,"线程id是%s"%na)
    lock.release()

for i in range(20):
    t = threading.Thread(target=func,args=(i,))
    t.start()

condition锁

import  threading

lock = threading.Condition()

def func(arg):       #根据用户动态输入的数据,决定一次性放行线程的个数
    lock.acquire()
    lock.wait()     #满足条件就就运行,不满足条件就等着
    print(arg)
    lock.release()


for i in range(20):
    t  = threading.Thread(target=func,args=(i,))
    t.start()



while True:
    inp = int(input(">>>"))   #一定要变成int类型
    lock.acquire()
    lock.notify(inp)
    lock.release()   

event锁(可联想红绿灯)

import time
import threading

lock = threading.Event()


def func(arg):
    print('线程来了')
    lock.wait() # 加锁:红灯
    print(arg)


for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

input(">>>>")   #这里输入东西就可以打开绿灯,进而将 0 1 2 3 4 5 6 7 8 9  依次打印出来
lock.set() # 绿灯       
import time
import threading

lock = threading.Event()


def func(arg):
    print('线程来了')
    lock.wait() # 加锁:红灯
    print(arg)


for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

input(">>>>")
lock.set() # 绿灯

# lock.clear() # 再次变红灯   这里如果不加红灯 接下来的十个线程,会同行,所以要在这里再次加上红灯,
然后再次输入任意字符进行放行
for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() input(">>>>") lock.set()

三   threading.local                                                                                                                                                                                 

import time
import threading

v = threading.local()

def func(arg):
    # 内部会为当前线程创建一个空间用于存储:phone=自己的值
    v.phone = arg     
    # time.sleep(0.1)
    print(v.phone,arg,"**") # 去当前线程自己空间取值   红色标注的这个是活的

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()
#原理
import
time import threading DATA_DICT = {} def func(arg): ident = threading.get_ident() DATA_DICT[ident] = arg time.sleep(1) print(DATA_DICT[ident],arg) for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
import time
import threading
INFO = {}
class Local(object):

    def __getattr__(self, item):
        ident = threading.get_ident()
        return INFO[ident][item]

    def __setattr__(self, key, value):
        ident = threading.get_ident()
        if ident in INFO:
            INFO[ident][key] = value
        else:
            INFO[ident] = {key:value}

obj = Local()

def func(arg):
    obj.phone = arg # 调用对象的类中 __setattr__方法(“phone”,1)
    time.sleep(2)
    print(obj.phone,arg)  #会自动调用类中__getattr__
for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
 

四 线程池                                                                                                                                                                                                

 

from concurrent.futures import ThreadPoolExecutor
import time

def task(a1,a2):
    # time.sleep(0.3)
    print(a1,a2)

# 创建了一个线程池(最多5个线程)
pool = ThreadPoolExecutor(5)


for i in range(6):
    # 去线程池中申请一个线程,让线程执行task函数。(最多申请到5个,5个以后就会比之前的慢一点,因为只能等之前的线程池执行完毕,才能接着接线程)
    pool.submit(task,i,8)

 

四生穿着消费者模型

import time
import queue
import threading
q = queue.Queue() # 线程安全

def producer(id):
    """
    生产者
    :return:
    """
    while True:
        time.sleep(2)
        q.put('包子')
        print('厨师%s 生产了一个包子' %id )

for i in range(1,4):
    t = threading.Thread(target=producer,args=(i,))
    t.start()


def consumer(id):
    """
    消费者
    :return:
    """
    while True:
        time.sleep(1)
        v1 = q.get()
        print('顾客 %s 吃了一个包子' % id)

for i in range(1,3):
    t = threading.Thread(target=consumer,args=(i,))
    t.start()

 

posted @ 2018-09-11 17:56  团子emma  阅读(163)  评论(0)    收藏  举报