python多线程编程4: 死锁和可重入锁
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用的停止响应。下面看一个死锁的例子:
# encoding: UTF-8 import threading import time class MyThread(threading.Thread): def do1(self): global resA, resB if mutexA.acquire(): msg = self.name+' got resA' print msg if mutexB.acquire(1): msg = self.name+' got resB' print msg mutexB.release() mutexA.release() def do2(self): global resA, resB if mutexB.acquire(): msg = self.name+' got resB' print msg if mutexA.acquire(1): msg = self.name+' got resA' print msg mutexA.release() mutexB.release() def run(self): self.do1() self.do2() resA = 0 resB = 0 mutexA = threading.Lock() mutexB = threading.Lock() def test(): for i in range(5): t = MyThread() t.start() if __name__ == '__main__': test()
执行结果:
Thread-1 got resA
Thread-1 got resB
Thread-1 got resB
Thread-1 got resA
Thread-2 got resA
Thread-2 got resB
Thread-2 got resB
Thread-2 got resA
Thread-3 got resA
Thread-3 got resB
Thread-3 got resB
Thread-3 got resA
Thread-5 got resA
Thread-5 got resB
Thread-5 got resB
Thread-4 got resA
此时进程已经死掉。
可重入锁
更简单的死锁情况是一个线程“迭代”请求同一个资源,直接就会造成死锁:
import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = self.name+' set num to '+str(num) print msg mutex.acquire() mutex.release() mutex.release() num = 0 mutex = threading.Lock() def test(): for i in range(5): t = MyThread() t.start() if __name__ == '__main__': test()
为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = self.name+' set num to '+str(num) print msg mutex.acquire() mutex.release() mutex.release() num = 0 mutex = threading.RLock() def test(): for i in range(5): t = MyThread() t.start() if __name__ == '__main__': test()
执行结果:
Thread-1 set num to 1
Thread-3 set num to 2
Thread-2 set num to 3
Thread-5 set num to 4
Thread-4 set num to 5

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

C++中使用互斥量(mutex)处理多线程共享资源:通过std::mutex创建互斥量。使用mtx.lock()获取互斥量,对共享资源进行排他访问。使用mtx.unlock()释放互斥量。

多线程程序测试面临不可重复性、并发错误、死锁和缺乏可视性等挑战。策略包括:单元测试:针对每个线程编写单元测试,验证线程行为。多线程模拟:使用模拟框架在控制线程调度的情况下测试程序。数据竞态检测:使用工具查找潜在的数据竞态,如valgrind。调试:使用调试器(如gdb)检查运行时程序状态,找到数据竞争根源。

在多线程环境中,C++内存管理面临以下挑战:数据竞争、死锁和内存泄漏。应对措施包括:1.使用同步机制,如互斥锁和原子变量;2.使用无锁数据结构;3.使用智能指针;4.(可选)实现垃圾回收。

C++多线程编程的调试技巧包括:使用数据竞争分析器检测读写冲突,并使用同步机制(如互斥锁)解决。使用线程调试工具检测死锁,并通过避免嵌套锁和使用死锁检测机制来解决。使用数据竞争分析器检测数据竞争,并通过将写入操作移入关键段或使用原子操作来解决。使用性能分析工具测量上下文切换频率,并通过减少线程数量、使用线程池和卸载任务来解决过高的开销。

Python 使初学者能够解决问题。其用户友好的语法、广泛的库以及变量、条件语句和循环等功能可实现高效的代码开发。从管理数据到控制程序流程和执行重复任务,Python 提供了

C++编程谜题涵盖斐波那契数列、阶乘、汉明距离、数组最大值和最小值等算法和数据结构概念,通过解决这些谜题,可以巩固C++知识,提升算法理解和编程技巧。

C++多线程同步关键概念:互斥锁:确保临界区只能由一个线程访问。条件变量:线程可在特定条件满足时被唤醒。原子操作:不可中断的单一CPU指令,保证共享变量修改的原子性。

多线程死锁预防机制包括:1.锁顺序;2.测试并设置。检测机制包括:1.超时;2.死锁检测器。文章举例共享银行账户,通过锁顺序避免死锁,为转账函数先请求转出账户再请求转入账户的锁。
