Multithreading Concepts: Locks, Deadlock, Recursive Locks, and Daemon Threads
This article explains multithreading fundamentals, covering thread concepts, lock mechanisms for database access, deadlock causes and solutions, recursive locks (RLock), data race issues, and daemon thread behavior. It also discusses connection pooling, timeout strategies to avoid deadlock, and practical code examples in Python.
Multithreading (英语:multithreading)是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。
多线程在读数据库时,会有资源的竞争问题。因为一个 connection 在同一时间只能被一个线程占用,其他线程没办法读取。一个解决办法就是开启多个 connection ,每个线程使用一个,但这样会浪费资源。最好的办法是多个线程共用一个 connection :当一个线程读取数据后,将 connection 给下一个线程使用,这就需要锁来实现。简单来说,锁就是在数据库读写时加个标志,当需要读取数据库时,先锁定,读取完成后再解锁,然后另一个线程要读取数据库之前,先判断锁的状态,如果是锁定状态,就先等待,等到解锁后再读取数据库。
所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。例如,线程 1 将 mutex_x 上了锁,等着锁 mutex_y ;与此同时,线程 2 已经将 mutex_y 上了锁,等着锁 mutex_x 。这样就形成了死锁。在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用的停止响应。在程序设计时,要尽量避免死锁的出现。为了避免死锁一直阻塞下去,可以在其中一方添加超时时间,如果超时了,就跳过。
递归锁(RLock,可重入锁):当一个线程中遇到锁嵌套情况该怎么办,又会遇到什么情况?这是一个很简单的线程锁死案例,程序将被卡死,停止不动。为了解决这一情况,Python 提供了递归锁 RLock(可重入锁)。这个 RLock 内部维护着一个 Lock 和一个 counter 变量,counter 记录了 acquire 的次数,从而使得资源可以被多次 require。直到一个线程所有的 acquire 都被 release,其他的线程才能获得资源。上面的代码只需做一些小小的改动。
数据错乱:由于多个线程之间可以共享数据,随之而来的问题就是:多个线程同时更改一个变量、使用一个资源时,就会出现数据错乱、死锁等现象。答案:访问之前锁住资源,用完之后释放资源。
守护线程:将线程设置为守护线程。若设置为守护线程,主线程结束后,子线程也将结束,并且主线程不会理会子线程是否结束,主线程不会等待子线程结束完后才结束。若没有设置为守护线程,主线程会等待子线程结束后才会结束。
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.