Python中的线程和进程

线程和进程是计算机科学中一个非常重要的概念。比如执行一个应用程序,它就是一个独立的进程。这个应用程序里面会执行不同的任务,这些任务是由线程来完成的。一个进程至少有一个线程来完成应用程序的功能。多进程意味着可以创建多个互相之间独立的应用程序,多线程则意味着一个独立的进程当中可以同时执行不同的任务。

多进程

Unix/Linux系统提供了一个fork()系统函数调用,当调用该函数,操作系统自动将当前进程(父进程)复制一份(子进程),然后分别在父进程和子进程当中返回。子进程当中永远返回0,父进程则返回子进程的ID,这样父进程就可以知道fork出来的子进程的ID。子进程可以通过getpid()函数获取到父进程的ID。这些常见的系统调用封装在Python的os模块中:

多线程

Python中的标准库提供了_threadthreading模块两个线程模块,_thread是低级模块,threading是高级模块,它是对_thread模块进行了封装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import time, threading

def test_thread():
# current_thread() 返回当前的线程的实例
print('thread %s is running...' % threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('thread %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' % threading.current_thread().name)

print('thread %s is running...' % threading.current_thread().name)
# 创建名字为 LoopThread 新的线程
t = threading.Thread(target=test_thread, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)

# 输出
thread LoopThread is running...
>>> t.jothread LoopThread >>> 1
in()
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
>>> print('thread %s ended.' % threading.current_thread().name)

在使用多线程的时候,由于所有的变量都可以被任意线程访问,所有则该变量有可能被任何线程修改。

为了防止变量被任意线程更改,可以利用threading模块的Lock()实现。使用lock = threading.Lock()创建一个锁,使用lock.acquire()来将需要只能单一线程访问的资源加锁,这样别的线程就不能访问。访问紫竹院结束,使用lock.release()来释放锁。通常为了避免出现死锁的现象,我们可以使用try...finally...保证锁一定能被释放:

1
2
3
4
5
6
7
8
9
10
11
import threading

lock = threading.Lock()

try:
# do something in here ...
# 获取锁
lock.acquire()
finally:
# 释放锁
lock.release()