模拟线程上的死锁

时间:2013-01-11 22:59:26

标签: python process deadlock

我有3个线程,当前正在同时运行。

def f1():
    print "running first thread\n"
    sleep(10)

def f2():
    print "running second thread\n"
    sleep(10)

def f3():
    print "running third thread\n"
    sleep(10)


if __name__ == "__main__":
    thread1 = Thread(target = f1)
    thread2 = Thread(target = f2)
    thread3 = Thread(target = f3)

    try:
        thread1 = Thread(target = f1)
        thread1.start()

        thread2 = Thread(target = f2)
        thread2.start()

        thread3 = Thread(target = f3)   
        thread3.start()

        while(thread1.isAlive() or thread2.isAlive() or thread3.isAlive()): 
            thread1.join()
            thread2.join()
            thread3.join()  
    except (KeyboardInterrupt, SystemExit):
        sys.exit()

如何模拟死锁?另外,我怎样才能让每个线程一个接一个地运行?我还可以列出我脚本中当前运行的所有线程吗?或者给他们优先考虑?

3 个答案:

答案 0 :(得分:4)

  

如何模拟死锁?

所有死锁意味着阻止一个或多个线程取得任何进展,因此您可以使用单个线程模拟它。只需在while True:周围添加sleep(10)

在实际情况中,您通常会有两个线程同时阻止彼此进度。例如,也许他们以相反的顺序采取了一对锁,因此线程1将不会释放锁1直到它获得锁2,但是线程2将不会释放锁2直到它获得锁1.因此,它可能最好通过让两个线程永久阻塞来模拟它。

如果你想真正创建一个死锁,最简单的方法就是让线程在字面上相互阻塞:将thread2.join()添加到f1,将thread1.join()添加到f2 }。然后f1无法完成f2f2f1之前无法完成,因此任何人都无法完成。

但是,如果你想创建一个真实的死锁,你几乎肯定会想要使用像threading.Lock这样的同步对象来做类似上面描述的双锁情况。

  

另外,我怎样才能让每个线程在另一个之后运行?

嗯,简单的方法是首先不使用线程。但如果你真的想要,就这样做:

thread1.start()
thread1.join()
thread2.start()
thread2.join()
thread3.start()
thread3.join()
  

我还可以列出我脚本中当前运行的所有线程吗?

threading.enumerate()。除了调试之外,您通常不想使用它;如果您希望稍后访问它们(正如您所做的那样),请在创建时跟踪线程。

  

或给他们优先考虑?

正如文档所说:

  

目前,没有优先级,没有线程组,线程也无法销毁,停止,暂停,恢复或中断。

如果您需要此功能,则必须超出threading,例如,通过ctypeswin32api等使用原生API。

答案 1 :(得分:0)

如何模拟死锁?

import threading
import time

l1=threading.Lock()
l2 = threading.Lock()

def f1(name):
    print('thread',name,'about to lock l1')
    with l1:
        print('thread',name,'has lock l1')
        time.sleep(0.3)
        print('thread',name,'about to lock l2')
        with l2:
            print('thread',name,'run into deadLock,\nthis line will never run')

def f2(name):
    print('thread',name,'about to lock l2')
    with l2:
        print('thread',name,'has lock l2')
        time.sleep(0.3)
        print('thread',name,'about to lock l1')
        with l2:
            print('thread',name,'run into deadLock,\nthis line will never run')

if __name__ == '__main__':
    t1=threading.Thread(target=f1, args=['t1',])
    t2=threading.Thread(target=f2, args=['t2',])

    t1.start()
    t2.start()

输出:

$ python tmpThread.py
thread t1 about to lock l1
thread t2 about to lock l2
thread t1 has lock l1
thread t2 has lock l2
thread t1 about to lock l2
thread t2 about to lock l1

答案 2 :(得分:0)

经典的银行转账死锁示例。

from threading import Lock, Thread

accountone = Lock()
accounttwo = Lock()

def transfer(accountone, accounttwo):
    accountone.acquire()
    accounttwo.acquire()
    print("Transaction done")
    accountone.release()
    accounttwo.release()

def transfer_do(accountone, accounttwo):
    while True:
        transfer(accountone, accounttwo) # send money from first account to second
        transfer(accounttwo, accountone) # send money from second account to first

for x in range(30):
    t = Thread(target=transfer_do, args=(accountone, accounttwo))
    t.start()