避免线程/进程竞争、死锁的优化策略
- 锁机制
- 互斥锁(Mutex):用于保护共享资源,同一时间只有一个线程/进程能获取锁访问资源。例如在Python的
threading
模块中:
import threading
# 创建互斥锁
mutex = threading.Lock()
shared_resource = 0
def worker():
global shared_resource
mutex.acquire()
try:
shared_resource += 1
finally:
mutex.release()
threads = []
for _ in range(10):
t = threading.Thread(target=worker)
threads.append(t)
t.start()
for t in threads:
t.join()
print(shared_resource)
- **读写锁(Read - Write Lock)**:允许多个线程同时读共享资源,但写操作时需要独占。在C++中可以使用`std::shared_mutex`实现读写锁:
#include <iostream>
#include <thread>
#include <shared_mutex>
std::shared_mutex mtx;
int data = 0;
void read() {
mtx.lock_shared();
std::cout << "Read data: " << data << std::endl;
mtx.unlock_shared();
}
void write() {
mtx.lock();
data++;
std::cout << "Write data: " << data << std::endl;
mtx.unlock();
}
int main() {
std::thread t1(read);
std::thread t2(write);
std::thread t3(read);
t1.join();
t2.join();
t3.join();
return 0;
}
- 信号量(Semaphore):控制同时访问共享资源的线程/进程数量。在Java中使用
Semaphore
类:
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
private static final int MAX_THREADS = 3;
private static final Semaphore semaphore = new Semaphore(MAX_THREADS);
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is accessing the resource.");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " is leaving the resource.");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
- 资源分配图算法(预防死锁):通过对资源分配进行检查,确保系统不会进入死锁状态。例如银行家算法,通过预先判断资源分配是否安全来避免死锁。
- 避免嵌套锁:尽量避免一个线程/进程获取多个锁的嵌套情况。如果无法避免,确保所有线程/进程获取锁的顺序一致。例如:
lock1 = threading.Lock()
lock2 = threading.Lock()
# 所有线程都按照这种顺序获取锁
def thread_function1():
lock1.acquire()
try:
lock2.acquire()
try:
# 操作共享资源
pass
finally:
lock2.release()
finally:
lock1.release()
def thread_function2():
lock1.acquire()
try:
lock2.acquire()
try:
# 操作共享资源
pass
finally:
lock2.release()
finally:
lock1.release()
- 使用线程安全的数据结构:如Java中的
ConcurrentHashMap
,Python中的queue.Queue
等。以Python的queue.Queue
为例:
import threading
import queue
q = queue.Queue()
def producer():
for i in range(5):
q.put(i)
def consumer():
while True:
item = q.get()
if item is None:
break
print(f"Consumed: {item}")
q.task_done()
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)
producer_thread.start()
consumer_thread.start()
producer_thread.join()
q.put(None)
consumer_thread.join()
- 线程/进程池:使用线程池或进程池可以减少线程/进程创建和销毁的开销,同时可以限制并发的数量,降低竞争风险。在Python中使用
concurrent.futures
模块的线程池:
import concurrent.futures
def task(x):
return x * x
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(task, range(10)))
print(results)
提高系统稳定性和性能的策略
- 减少共享资源:尽量减少线程/进程间共享的资源,降低竞争的可能性。如果可能,将数据进行分区,让每个线程/进程处理自己独立的数据部分。
- 优化算法和数据结构:选择合适的算法和数据结构可以提高效率,减少锁的持有时间。例如,使用哈希表代替线性查找的数据结构。
- 异步编程:对于I/O密集型任务,使用异步编程模型,如Python的
asyncio
库。这样线程/进程在等待I/O操作完成时不会阻塞,提高系统的并发性能。
import asyncio
async def io_bound_task():
await asyncio.sleep(1)
return "Task completed"
async def main():
tasks = [io_bound_task() for _ in range(5)]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
- 资源预分配:提前分配好所需的资源,避免在运行过程中频繁申请和释放资源导致的竞争。例如,在启动时分配好内存池。