python 同步锁_Python 线程同步锁, 信号量

同步锁

import time, threading

def addNum():

global num

num -= 1

num = 100

thread_list = []

for i in range(100):

t = threading.Thread(target=addNum)

t.start()

thread_list.append(t)

for t in thread_list:

t.join()

print('final num:', num)

运行结果:

final num: 0

import time, threading

def addNum():

global num

#num -= 1

tmp = num

time.sleep(0.00001)

num = tmp - 1

num = 100

thread_list = []

for i in range(100):

t = threading.Thread(target=addNum)

t.start()

thread_list.append(t)

for t in thread_list:

t.join()

print('final num:', num)

运行结果:

final num: 93

final num: 91

final num: 94

原因:

第一个程序中,num -= 1 这种写法,程序执行动作太快(完成这个动作在 cup 切换的时间内)

第二个程序中,把 num -= 1 , 加入了 sleep 时间,100个线程存在没有执行完就进行了切换,导致全局的 num 没有正常返回。引用下大神的图发现总结得非常好:

a807dd37c5dcf8e708a1cb787822ecdb.png

在上面的例子中 使用 join 方法会把整个线程停住,造成了串行,失去了多线程的意义,我们只需要在涉及到计算公共数据的时候串行执行即可。

使用同步锁处理计算公共的数据

import time, threading

def addNum():

global num

lock.acquire()

tmp = num

time.sleep(0.00001)

num = tmp - 1

lock.release()

num = 100

lock = threading.Lock()

thread_list = []

for i in range(100):

t = threading.Thread(target=addNum)

t.start()

thread_list.append(t)

for t in thread_list:

t.join()

print('final num:', num)

运算结果:

final num: 0

线程死锁和递归锁

import threading, time

class myThread(threading.Thread):

def doA(self):

lockA.acquire()

print(self.name, "gotlockA", time.ctime())

time.sleep(3)

lockB.acquire()

print(self.name, "gotlockB", time.ctime())

lockB.release()

lockA.release()

def doB(self):

lockB.acquire()

print(self.name, "gotlockB", time.ctime())

time.sleep(2)

lockA.acquire()

print(self.name, "gotlockA", time.ctime())

lockA.release()

lockB.release()

def run(self):

self.doA()

self.doB()

if __name__ == '__main__':

lockA = threading.Lock()

lockB = threading.Lock()

threads = []

for i in range(5):

threads.append(myThread())

for t in threads:

t.start()

for t in threads:

t.join()

#运行结果:

Thread-1 gotlockA Sat Jul 28 15:09:31 2018

Thread-1 gotlockB Sat Jul 28 15:09:34 2018

Thread-1 gotlockB Sat Jul 28 15:09:34 2018

Thread-2 gotlockA Sat Jul 28 15:09:34 2018

使用递归锁

import threading, time

class myThread(threading.Thread):

def doA(self):

lock.acquire()

print(self.name, "gotlockA", time.ctime())

time.sleep(3)

lock.acquire()

print(self.name, "gotlockB", time.ctime())

lock.release()

lock.release()

def doB(self):

lock.acquire()

print(self.name, "gotlockB", time.ctime())

time.sleep(2)

lock.acquire()

print(self.name, "gotlockA", time.ctime())

lock.release()

lock.release()

def run(self):

self.doA()

self.doB()

if __name__ == '__main__':

lock = threading.RLock()

threads = []

for i in range(5):

threads.append(myThread())

for t in threads:

t.start()

for t in threads:

t.join()

运行结果:

Thread-1 gotlockA Sat Jul 28 15:19:35 2018

Thread-1 gotlockB Sat Jul 28 15:19:38 2018

Thread-1 gotlockB Sat Jul 28 15:19:38 2018

Thread-1 gotlockA Sat Jul 28 15:19:40 2018

Thread-3 gotlockA Sat Jul 28 15:19:40 2018

Thread-3 gotlockB Sat Jul 28 15:19:43 2018

Thread-3 gotlockB Sat Jul 28 15:19:43 2018

Thread-3 gotlockA Sat Jul 28 15:19:45 2018

Thread-5 gotlockA Sat Jul 28 15:19:45 2018

Thread-5 gotlockB Sat Jul 28 15:19:48 2018

Thread-5 gotlockB Sat Jul 28 15:19:48 2018

Thread-5 gotlockA Sat Jul 28 15:19:50 2018

Thread-4 gotlockA Sat Jul 28 15:19:50 2018

Thread-4 gotlockB Sat Jul 28 15:19:53 2018

Thread-4 gotlockB Sat Jul 28 15:19:53 2018

Thread-4 gotlockA Sat Jul 28 15:19:55 2018

Thread-2 gotlockA Sat Jul 28 15:19:55 2018

Thread-2 gotlockB Sat Jul 28 15:19:58 2018

Thread-2 gotlockB Sat Jul 28 15:19:58 2018

Thread-2 gotlockA Sat Jul 28 15:20:00 2018

信号量

信号量用来控制线程并发数的,BoundedSemaphore或Semaphore管理一个内置的计数 器,每当调用acquire()时-1,调用release()时+1,计数器不能小于0,当计数器为 0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()。(类似于停车位的概念)。

BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release()时检查计数 器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。

import threading, time

class myThread(threading.Thread):

def run(self):

if semaphore.acquire():

print(self.name)

time.sleep(5)

semaphore.release()

if __name__ == "__main__":

semaphore = threading.Semaphore(5)

thrs = []

for i in range(20):

thrs.append(myThread())

for t in thrs:

t.start()

#运行结果:

Thread-1

Thread-2

Thread-3

Thread-4

Thread-5

Thread-6

Thread-7

Thread-9

Thread-10

Thread-8

Thread-11

Thread-13

Thread-14

Thread-12

Thread-15

Thread-18

Thread-16

Thread-17

Thread-19

Thread-20

import threading, time

class myThread(threading.Thread):

def run(self):

if semaphore.acquire():

print(self.name)

time.sleep(5)

semaphore.release()

if __name__ == "__main__":

semaphore = threading.BoundedSemaphore(5)

thrs = []

for i in range(20):

thrs.append(myThread())

for t in thrs:

t.start()

#运行结果:

Thread-1

Thread-2

Thread-3

Thread-4

Thread-5

Thread-6

Thread-8

Thread-10

Thread-9

Thread-7

Thread-12

Thread-14

Thread-15

Thread-13

Thread-11

Thread-16

Thread-17

Thread-20

Thread-19

Thread-18

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值