面试题答案
一键面试常用线程同步机制
- Lock(锁):用于防止多个线程同时访问共享资源,同一时间只有一个线程可以获得锁并执行相关代码,其他线程需等待锁的释放。
- Semaphore(信号量):可以控制同时访问共享资源的线程数量,允许多个线程同时访问,但数量受信号量初始值限制。
- Condition(条件变量):允许线程在满足特定条件时才执行,线程可以等待某个条件满足并在条件满足时被唤醒。
- Event(事件):用于线程间通信,一个线程可以通过设置事件来通知其他线程执行某些操作,其他线程可以等待事件被设置。
使用Lock实现线程同步
import threading
# 共享资源
count = 0
lock = threading.Lock()
def increment():
global count
for _ in range(1000000):
lock.acquire()
try:
count += 1
finally:
lock.release()
threads = []
for _ in range(2):
t = threading.Thread(target=increment)
threads.append(t)
t.start()
for t in threads:
t.join()
print(f"Final count: {count}")
在上述代码中,Lock
对象lock
用于确保在对count
进行增加操作时,同一时间只有一个线程可以执行,避免了竞态条件。
使用Semaphore实现线程同步
import threading
# 创建一个信号量,允许最多3个线程同时访问
semaphore = threading.Semaphore(3)
def task():
semaphore.acquire()
try:
print(f"{threading.current_thread().name} has entered the critical section.")
# 模拟一些工作
import time
time.sleep(2)
print(f"{threading.current_thread().name} is leaving the critical section.")
finally:
semaphore.release()
threads = []
for i in range(5):
t = threading.Thread(target=task)
threads.append(t)
t.start()
for t in threads:
t.join()
在这段代码中,Semaphore
对象semaphore
初始化为3,意味着最多可以有3个线程同时进入临界区执行任务,其他线程需要等待信号量的释放。
Lock和Semaphore的区别
- 可同时访问线程数量:
- Lock:同一时间只允许一个线程获得锁并进入临界区,是二元信号量(信号量值为0或1)的一种特殊情况。
- Semaphore:可以设置允许同时进入临界区的线程数量,初始值大于1时允许多个线程同时访问共享资源。
- 应用场景:
- Lock:适用于对共享资源的独占访问,例如对全局变量的修改,以防止数据竞争。
- Semaphore:适用于需要限制同时访问共享资源的线程数量的场景,比如限制数据库连接池的并发使用数量等。