浅谈Python中的Semaphore(信号量)与Lock(锁)

一、Semaphore(信号量)

Semaphore(信号量)是一种同步机制,用于控制多个线程对共享资源的访问。Semaphore可以控制同时访问共享资源的线程数量,从而避免资源竞争和死锁。

Semaphore有两个主要的操作:acquire(获取)和release(释放)。当一个线程需要访问共享资源时,它会调用Semaphore的acquire方法来获取一个信号量。如果此时Semaphore的计数器为0,则线程会被阻塞,直到有一个信号量可用。当线程完成对共享资源的访问后,它会调用Semaphore的release方法来释放一个信号量,使得其他线程可以继续访问共享资源。

下面是一个简单的Semaphore使用示例:

import threading

# 创建一个Semaphore对象,初始计数器为3
semaphore = threading.Semaphore(3)

def worker():
    # 获取一个信号量
    semaphore.acquire()
    print('Thread {} is working'.format(threading.current_thread().name))
    # 模拟工作时间
    for i in range(5):
        print('Thread {} is working ({}/5)'.format(threading.current_thread().name, i+1))
    # 释放一个信号量
    semaphore.release()

# 创建5个线程
threads = []
for i in range(5):
    t = threading.Thread(target=worker, name='Thread-{}'.format(i+1))
    threads.append(t)

# 启动线程
for t in threads:
    t.start()

# 等待所有线程完成
for t in threads:
    t.join()

在上面的示例中,我们创建了一个Semaphore对象,并将初始计数器设置为3。然后创建了5个线程,每个线程都会调用worker函数来模拟对共享资源的访问。在worker函数中,我们首先调用Semaphore的acquire方法来获取一个信号量,然后进行模拟工作,最后调用Semaphore的release方法来释放一个信号量。由于Semaphore的初始计数器为3,因此最多只有3个线程可以同时访问共享资源,其他线程会被阻塞,直到有一个信号量可用。

二、Lock(锁)

Lock(锁)是一种同步机制,用于控制多个线程对共享资源的访问。Lock可以确保在任何时刻只有一个线程可以访问共享资源,从而避免资源竞争和死锁。

在Python中,Lock可以使用threading模块中的Lock类来实现。Lock类有两个主要的操作:acquire(获取)和release(释放)。当一个线程需要访问共享资源时,它会调用Lock的acquire方法来获取锁。如果此时锁已经被其他线程占用,则线程会被阻塞,直到锁被释放。当线程完成对共享资源的访问后,它会调用Lock的release方法来释放锁,使得其他线程可以继续访问共享资源。

下面是一个简单的Lock使用示例:

import threading

# 创建一个Lock对象
lock = threading.Lock()

# 共享变量
count = 0

def worker():
    global count
    # 获取锁
    lock.acquire()
    print('Thread {} is working'.format(threading.current_thread().name))
    # 修改共享变量
    for i in range(100000):
        count += 1
    # 释放锁
    lock.release()

# 创建5个线程
threads = []
for i in range(5):
    t = threading.Thread(target=worker, name='Thread-{}'.format(i+1))
    threads.append(t)

# 启动线程
for t in threads:
    t.start()

# 等待所有线程完成
for t in threads:
    t.join()

# 输出共享变量的值
print('count =', count)

 

在上面的示例中,我们创建了一个Lock对象,并将其赋值给变量lock。然后创建了5个线程,每个线程都会调用worker函数来修改共享变量count。在worker函数中,我们首先调用Lock的acquire方法来获取锁,然后进行修改共享变量的操作,最后调用Lock的release方法来释放锁。由于Lock只允许一个线程访问共享资源,因此对共享变量的修改是安全的。

需要注意的是,在使用Lock时,一定要确保在修改共享资源之前获取锁,在修改完成之后释放锁,否则可能会导致死锁或者资源竞争的问题。

三、Semaphore跟Lock有什么区别

Semaphore和Lock都是用于控制多个线程对共享资源的访问的同步机制,但它们有一些区别。

1.控制访问数量:Semaphore可以控制同时访问共享资源的线程数量,而Lock只能控制同时只有一个线程访问共享资源。

2.计数器:Semaphore有一个计数器,每次acquire操作会将计数器减1,每次release操作会将计数器加1。而Lock没有计数器,只有一个锁状态。

3.等待机制:当一个线程调用Semaphore的acquire方法时,如果计数器为0,则线程会被阻塞,直到有一个信号量可用。而当一个线程调用Lock的acquire方法时,如果锁已经被其他线程占用,则线程会被阻塞,直到锁被释放。

4.用途:Semaphore适用于控制对一组资源的访问,例如线程池、数据库连接池等。而Lock适用于控制对单个资源的访问,例如共享变量、文件等。

总的来说,Semaphore比Lock更加灵活,可以控制多个线程同时访问共享资源的数量,而Lock只能控制一个线程访问共享资源。但在某些情况下,Lock可能更加简单和高效。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值