python 线程池 锁_python 线程池和锁

一.死锁现象与递归锁

锁:Lock线程安全,多线程操作时,内部会让所有线程排队处理。如:list/dict/Queue

线程不安全 + 人 => 排队处理。

importthreadingimporttime

v=[]

lock=threading.Lock()deffunc(arg):

lock.acquire()

v.append(arg)

time.sleep(0.01)

m= v[-1]print(arg,m)

lock.release()for i in range(10):

t=threading.Thread(target=func,args=(i,))

t.start()

锁:RLock

importthreadingimporttime

v=[]

lock=threading.RLock()deffunc(arg):

lock.acquire()

lock.acquire()

v.append(arg)

time.sleep(0.01)

m= v[-1]print(arg,m)

lock.release()

lock.release()for i in range(10):

t=threading.Thread(target=func,args=(i,))

t.start()

锁:BoundedSemaphore

importtimeimportthreading

lock= threading.BoundedSemaphore(3)deffunc(arg):

lock.acquire()print(arg)

time.sleep(1)

lock.release()for i in range(20):

t=threading.Thread(target=func,args=(i,))

t.start()

锁:condition

importtimeimportthreading

lock=threading.Condition()############### 方式一 ##############

deffunc(arg):print('线程进来了')

lock.acquire()

lock.wait()#加锁

print(arg)

time.sleep(1)

lock.release()for i in range(10):

t=threading.Thread(target=func,args=(i,))

t.start()whileTrue:

inp= int(input('>>>'))

lock.acquire()

lock.notify(inp)

lock.release()############### 方式二 ##############

"""def xxxx():

print('来执行函数了')

input(">>>")

# ct = threading.current_thread() # 获取当前线程

# ct.getName()

return True

def func(arg):

print('线程进来了')

lock.wait_for(xxxx)

print(arg)

time.sleep(1)

for i in range(10):

t =threading.Thread(target=func,args=(i,))

t.start()"""

锁:Event

importtimeimportthreading

lock=threading.Event()deffunc(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 的作用及原理

作用:内部自动为每个线程维护一个空间(字典),用于存取属于自己的值.保证线程之间的数据隔离.

importtimeimportthreading

v=threading.local()deffunc(arg):#内部会为当前线程创建一个空间用于存储:phone=自己的值

v.phone =arg

time.sleep(2)print(v.phone,arg) #去当前线程自己空间取值

for i in range(10):

t=threading.Thread(target=func,args=(i,))

t.start()

原理:

#原理1

importtimeimportthreading

DATA_DICT={}deffunc(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()#原理2

importtimeimportthreading

INFO={}classLocal(object):def __getattr__(self, item):

ident=threading.get_ident()returnINFO[ident][item]def __setattr__(self, key, value):

ident=threading.get_ident()if ident inINFO:

INFO[ident][key]=valueelse:

INFO[ident]={key:value}

obj=Local()deffunc(arg):

obj.phone= arg #调用对象的 __setattr__方法(“phone”,1)

time.sleep(2)print(obj.phone,arg)for i in range(10):

t=threading.Thread(target=func,args=(i,))

t.start()

三.线程池

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

from concurrent.futures importThreadPoolExecutorimporttimedeftask(a1,a2):

time.sleep(2)print(a1,a2)#创建了一个线程池(最多5个线程)

pool = ThreadPoolExecutor(5)for i in range(40):#去线程池中申请一个线程,让线程执行task函数。

pool.submit(task,i,8)

四.生产者消费者模型

产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者;生产者和消费者之间的中介就叫做缓冲区。

importtimeimportqueueimportthreading

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

defproducer(id):"""生产者

:return:"""

whileTrue:

time.sleep(2)

q.put('包子')print('厨师%s 生产了一个包子' %id )for i in range(1,4):

t= threading.Thread(target=producer,args=(i,))

t.start()defconsumer(id):"""消费者

:return:"""

whileTrue:

time.sleep(1)

v1=q.get()print('顾客 %s 吃了一个包子' %id)for i in range(1,3):

t= threading.Thread(target=consumer,args=(i,))

t.start()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值