1. 基本概念
进程(Process)
进程是一个程序的实例,是操作系统分配资源和调度的基本单位。每个进程都有独立的内存空间。适合需要强隔离的任务。
线程(Thread)
线程是进程中的一个执行单元,是CPU调度的基本单位。一个进程可以包含多个线程,这些线程共享进程的内存空间。适合需要轻量级并发的任务。
协程(Coroutine)
协程是一种更加轻量级的线程,可以在一个线程内实现并发。协程由程序员手动调度,而非操作系统。适合I/O密集型任务和需要大量并发的场景。
并发
在同一时间段内,多个任务(共享资源)在一个或多个处理器上交替进行执行。并发系统通过分时复用(time-sharing)使多个任务看似同时进行,虽然在任意时刻,单个处理器只能执行一个任务。
并行
在同一时间点上,多个任务(独立执行)在多个处理器上同时进行执行的能力。并行处理需要硬件支持(多核处理器或多处理器系统)。
多线程:多线程允许程序并发执行多个任务,适用于需要处理多个独立任务的场景。
2. 进程之间通信与同步
通信:主要解决进程之间的数据交换问题。
同步:主要解决进程之间的执行顺序和资源访问协调问题。
进程之间通信
进程之间通信是指多个进程之间交换数据的机制。这种机制允许进程彼此发送和接收信息,以便协调工作或共享数据。常见的进程间通信方式包括:
1. 管道(Pipe)
管道是一种半双工的通信方式,数据只能单向流动。通常用于具有亲缘关系的进程之间的通信(如父子进程)。
import os
r, w = os.pipe()
pid = os.fork()
if pid > 0:
# Parent process
os.close(r)
w = os.fdopen(w, 'w')
w.write("Hello from parent")
w.close()
else:
# Child process
os.close(w)
r = os.fdopen(r)
print(r.read())
r.close()
2. 消息队列(Message Queue)
消息队列是操作系统提供的一种消息传递机制,允许一个或多个进程将消息放入队列中,其他进程可以从队列中读取消息。消息队列提供了有序的消息传递方式。
import sysv_ipc
key = 1234
mq = sysv_ipc.MessageQueue(key, sysv_ipc.IPC_CREAT)
pid = os.fork()
if pid > 0:
mq.send(b"Hello from parent")
else:
message, _ = mq.receive()
print(message.decode())
3. 共享内存(Shared Memory)
共享内存是一种高效的进程间通信方式,多个进程可以直接读写同一块内存区域。由于内存是共享的,进程之间不需要进行数据的复制,但需要使用同步机制(如信号量)来避免竞争条件和保证数据一致性。
import mmap
import os
size = 1024
shm = mmap.mmap(-1, size)
pid = os.fork()
if pid > 0:
shm.write(b"Hello from parent")
else:
shm.seek(0)
print(shm.read(size).decode())
4. 信号(Signal)
信号是一种用于进程间通知的机制,一个进程可以向另一个进程发送信号,通知其发生了某个事件。信号主要用于进程间的简单通信和控制,如终止进程、暂停进程等。
import os
import signal
def handler(signum, frame):
print("Received signal:", signum)
signal.signal(signal.SIGUSR1, handler)
pid = os.fork()
if pid > 0:
os.kill(pid, signal.SIGUSR1)
else:
signal.pause()
5. 套接字(Socket)
套接字是一种更通用的通信机制,既可以用于同一台机器上的进程间通信,也可以用于网络上的进程间通信。套接字支持多种协议,如TCP和UDP,提供了强大的通信能力。
import socket
import os
def server():
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind("/tmp/socket")
s.listen(1)
conn, _ = s.accept()
print(conn.recv(1024).decode())
conn.close()
s.close()
def client():
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/tmp/socket")
s.send(b"Hello from client")
s.close()
pid = os.fork()
if pid > 0:
server()
else:
client()
6. 信号量(Semaphore)
信号量是一种用于同步进程或线程的机制,可以用来控制对公共资源的访问。信号量通过计数器来控制访问资源的进程数,是一种有效的并发控制手段。
7. 内存映射文件(Memory-Mapped File)
内存映射文件是一种将文件映射到进程的地址空间的技术,多个进程可以通过内存映射文件共享数据。内存映射文件不仅可以用于进程间通信,还可以用于文件I/O操作。
进程之间同步
进程之间同步是指协调多个进程的执行顺序,以确保共享资源的正确访问和操作。进程同步的目的是避免竞争条件和数据不一致问题。常见的进程同步机制包括:
1. 信号量(Semaphore)
信号量是一种同步机制,可以控制多个进程对共享资源的访问。信号量通过一个计数器来管理资源的使用,保证在资源可用时允许进程访问资源,否则进程会被阻塞。
import multiprocessing
import time
def worker(semaphore, num):
semaphore.acquire()
print(f"Worker