当多个线程访问同一个函数时,我们是否需要显式地实现锁机制。
我有一个使用线程的程序。有两个线程,t1和t2。t1用于add1(),t2用于线程的subtract1().Both并发访问相同的函数myfunction(caller,num)
1.我使用变量functionLock**.在给定的程序中定义了一个简单的锁机制这是可靠的还是我们需要修改它。**
import time, threading
functionLock = '' # blank means lock is open
def myfunction(caller,num):
global functionLock
while functionLock!='': # check and wait until the lock is open
print "locked by "+ str(functionLock)
time.sleep(1)
functionLock = caller # apply lock
total=0
if caller=='add1':
total+=num
print"1. addition finish with Total:"+str(total)
time.sleep(2)
total+=num
print"2. addition finish with Total:"+str(total)
time.sleep(2)
total+=num
print"3. addition finish with Total:"+str(total)
else:
time.sleep(1)
total-=num
print"\nSubtraction finish with Total:"+str(total)
print '\n For '+caller+'() Total: '+str(total)
functionLock='' # release the lock
def add1(arg1, arg2):
print '\n START add'
myfunction('add1',10)
print '\n END add'
def subtract1():
print '\n START Sub'
myfunction('sub1',100)
print '\n END Sub'
def main():
t1 = threading.Thread(target=add1, args=('arg1','arg2'))
t2 = threading.Thread(target=subtract1)
t1.start()
t2.start()
if __name__ == "__main__":
main()产出如下:
START add
START Sub
1. addition finish with Total:10
locked by add1
locked by add1
2. addition finish with Total:20
locked by add1
locked by add1
3. addition finish with Total:30
locked by add1
For add1() Total: 30
END add
Subtraction finish with Total:-100
For sub1() Total: -100
END Sub2.我们可以不使用锁吗?
即使我不使用上述程序中定义的锁机制,从线程t1和t2来看,结果也是一样的。这是否意味着,当多个线程访问同一个函数时,python自动实现锁。
在上述程序中不使用锁functionLock的程序输出
START add
START Sub
1. addition finish with Total:10
Subtraction finish with Total:-100
For sub1() Total: -100
END Sub
2. addition finish with Total:20
3. addition finish with Total:30
For add1() Total: 30
END add谢谢!
发布于 2013-03-14 17:44:22
除了这个线程上关于忙于等待变量的其他注释之外,我想指出的是,您没有使用任何类型的原子交换可能会导致并发错误。即使您的测试执行不会导致出现这些事件,但如果在不同时间执行足够多的重复,则可能会出现以下事件序列:
线程1执行while functionLock!=''并获取False。然后,Thread#1被中断(优先执行其他东西),线程#2执行同一行,while functionLock!=''也得到False。在本例中,两个线程都进入了关键部分,这显然不是您想要的。特别是,在线程修改total的任何行中,结果可能都不是您预期的结果,因为这两个线程可以同时位于该部分。请参见以下示例:
total是10。为了简单起见,假设num总是1。Thread#1执行total+=num,它由三个操作组成:(i)加载total的值,(ii)添加num,(iii)将结果存储在total中。如果在(i)之后,Thread#1被抢占,Thread#2执行total-=num,则total设置为9。然后,Thread#1恢复。但是,它已经加载了total = 10,因此它添加了1并将11存储到total变量中。这有效地改变了Thread#2在无操作中的减量操作.
注意,在@ron链接的维基百科文章中,代码使用了一个xchg操作,它原子地用变量交换寄存器。这对于修正锁是至关重要的。总之,如果您想避开难以调试的并发错误,永远不要将自己的锁作为原子操作的替代。
编辑我刚刚注意到,实际上total是代码中的一个局部变量,所以这是不可能发生的。但是,我认为您没有意识到这是代码完美工作的原因,因为您肯定“这是否意味着当多个线程访问同一个函数时python自动实现锁”,这不是真的。请尝试将global total添加到myfunction的开头,并多次执行线程,您将在输出中看到错误。/edit
发布于 2013-03-14 06:19:44
虽然我对Python不太了解,但我想说,这与任何其他语言一样:
只要没有在函数之外声明并因此可以在线程之间共享的变量,就不应该需要锁。你的功能似乎不是这样的。
但是,控制台的输出可能会被混淆。
发布于 2013-03-14 06:20:31
当您认为正在编写的代码是关键部分代码时,您需要锁定,即代码段是否正在修改线程之间的共享状态,如果不是,则不需要担心锁定。
是否应该锁定方法是一种设计选择,理想情况下,您应该将锁锁定为更接近线程的共享状态访问。
https://stackoverflow.com/questions/15402452
复制相似问题