让我来详细讲解操作系统的同步和互斥。
同步和互斥的概念
在多任务操作系统中,多个程序同时运行,在数据访问、资源分配等方面存在并发的情况。同步和互斥是用来解决并发情况下保证数据的正确性和安全性的两个重要概念。
-
同步指的是多个任务按照一定的规律被调用,以便保证数据的一致性。例如读写文件时,读操作和写操作必须按照一定的顺序进行,否则会出现数据错误的情况。
-
互斥指的是用于限制共享资源在同一时间只被一个进程访问,从而避免数 据的不一致和冲突。例如多个进程同时写同一个全局变量,将会同时进行写操作,导致最终的结果并不准确。
同步和互斥的实现
常见的同步和互斥实现方式包括信号量、互斥锁和条件变量,下面我们分别讲解。
信号量
信号量是用来控制进程或线程同步访问共享资源的一种方法。在多个进程或线程间共享变量时,经常会产生冲突问题。这时可以使用信号量对共享资源进行加锁或解锁。
示例代码:
import threading
count = 0
semaphore = threading.Semaphore(1)
def increase():
global count
for i in range(1000):
semaphore.acquire()
count += 1
semaphore.release()
def decrease():
global count
for i in range(1000):
semaphore.acquire()
count -= 1
semaphore.release()
t1 = threading.Thread(target=increase)
t2 = threading.Thread(target=decrease)
t1.start()
t2.start()
t1.join()
t2.join()
print(count) # 输出结果应该为0
在上面的示例中,我们创建了一个计数器count
,并使用信号量semaphore
来保证两个线程按照一定的顺序对它进行读取和修改。
互斥锁
互斥锁是一种用于多线程编程中,防止多个线程同时对同一个共享资源进行互相干扰的机制。每次只有一个线程可以获取互斥锁,如果一个线程因为没有获取或者没有释放互斥锁而阻塞的话,就被称为出现了死锁。
示例代码:
import threading
count = 0
mutex = threading.Lock()
def increase():
global count
for i in range(1000):
mutex.acquire()
count += 1
mutex.release()
def decrease():
global count
for i in range(1000):
mutex.acquire()
count -= 1
mutex.release()
t1 = threading.Thread(target=increase)
t2 = threading.Thread(target=decrease)
t1.start()
t2.start()
t1.join()
t2.join()
print(count) # 输出结果应该为0
在上面的示例中,我们使用了Python内置的threading.Lock()
来创建一个互斥锁mutex
,并使用mutex.acquire()
和mutex.release()
对count
进行加锁和解锁。
条件变量
条件变量是用于多线程编程中,通过建立一个等待和通知机制的对象,解决某些线程等待的问题。当程序中有多个线程共同使用同一个共享资源时,需要某个线程修改共享资源时,其他线程必须等待,直到该线程修改完毕后通知其他线程继续使用共享资源。
示例代码:
import threading
import time
condition = threading.Condition()
queue = []
def produce():
global queue
while True:
if condition.acquire():
if len(queue) < 10:
item = time.strftime('%H:%M:%S', time.localtime())
queue.append(item)
print('Produced %s' % item)
condition.notify()
condition.release()
time.sleep(1)
def consume():
global queue
while True:
if condition.acquire():
while not queue:
print('Nothing in queue, consumer is waiting')
condition.wait()
item = queue.pop(0)
print('Consumed %s' % item)
condition.release()
time.sleep(2)
t1 = threading.Thread(target=produce)
t2 = threading.Thread(target=consume)
t1.start()
t2.start()
t1.join()
t2.join()
在上面的示例中,我们使用了Python内置的threading.Condition()
来创建一个条件变量condition
,并使用condition.wait()
和condition.notify()
来实现生产者和消费者线程之间的同步。生产者线程检查队列长度,如果小于10则向队列中添加项目并通知消费者线程,如果队列为空,消费者线程则等待生产者线程通知。