面试题答案
一键面试常见场景举例
- 共享变量操作
假设有一个全局变量
count
,两个线程都对其进行加1操作。例如:
import threading
count = 0
def increment():
global count
for _ in range(100000):
count = count + 1
thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=increment)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(count)
在这个例子中,count
是共享资源,两个线程同时对其进行修改。
- 文件读写操作 假设两个线程同时向同一个文件写入数据。例如:
import threading
def write_to_file():
with open('test.txt', 'a') as f:
f.write('Some data\n')
thread1 = threading.Thread(target=write_to_file)
thread2 = threading.Thread(target=write_to_file)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
这里test.txt
文件就是共享资源,两个线程都尝试对其进行写入。
出现资源竞争的原因
在Python多线程编程中,线程是共享进程的内存空间的。当多个线程同时访问和修改共享资源(如上述的共享变量或文件)时,由于线程的调度是由操作系统控制的,可能会发生以下情况:
- 指令交错执行:例如在对共享变量
count
进行count = count + 1
操作时,这个操作在CPU层面并非原子操作,可能会被拆分为读取count
值、加1、写回count
值这几个步骤。如果一个线程在读取count
值后,还未完成写回操作时,另一个线程也读取了count
值,那么它们就会基于相同的旧值进行加1,最终导致结果比预期少1。 - 缺乏同步机制:如果没有使用合适的同步工具(如锁)来协调线程对共享资源的访问,就无法保证线程对共享资源的操作是顺序执行的,从而导致资源竞争问题,使程序产生不可预测的结果。