12、第七周-网络编程 - 线程中的信号量(Semaphore)

  

  互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据。简单介绍如下:

  信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用的。
  也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务 并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥锁则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进 行操作。在有些情况下两者可以互换。

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

  • 创建 Create
  • 等待 Wait::线程等待信号量,如果值大于0,则获得,值减一;如果只等于0,则一直线程进入睡眠状态,知道信号量值大于0或者超时。
  • 释放 Post:执行释放信号量,则值加一;如果此时有正在等待的线程,则唤醒该线程。
  • 试图等待 TryWait:如果调用TryWait,线程并不真正的去获得信号量,还是检查信号量是否能够被获得,如果信号量值大于0,则TryWait返回成功;否则返回失败。
  • 销毁 Destroy

   Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥。Mutex对象的值,只有0和1两个值。这两个值也分别代表了Mutex的两种状态。值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待;值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。

Mutex可以被抽象为四个操作:

  • 创建 Create
  • 加锁 Lock
  • 解锁 Unlock
  • 销毁 Destroy

互斥锁和信号量的区别:

  • 互斥量用于线程的互斥,信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。
  1. 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
  2. 信号:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源
  • 互斥量值只能为0/1,信号量值可以为非负整数。
  1. 也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。
  • 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

举例:有三个公共电话亭,同时可以三个人打电话。这时候有人过来要打电话,就出现了等待。要等会里面的人出来后(里面的人出来这一动作,就相当于信号,告诉外面的人,到你打电话了),外面的人才能进去,进行下一步操作。

import threading,time

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print ("run the  thread:%s\n " % n)
    semaphore.release()

if __name__ == "__main__":
    semaphore = threading.BoundedSemaphore(4) #最多允许4个线程同时运行
    for i in range(10):
        t = threading.Thread(target=run,args=(i,))
        t.start()
while threading.active_count() != 1:
    pass
else:
    print("--all thread done--")
输出:
run the  thread:0
run the  thread:1
run the  thread:2
run the  thread:3

run the  thread:4
run the  thread:7
run the  thread:5
run the  thread:6

run the  thread:9
run the  thread:8

--all thread done--
Process finished with exit code 0
备注:每次执行4个线程,等前面执行完成后,在进行下一个。最后剩下两个,会一起执行。整个执行过程中是无序的。

原文地址:https://www.cnblogs.com/chen170615/p/8746546.html

时间: 2024-10-19 06:26:37

12、第七周-网络编程 - 线程中的信号量(Semaphore)的相关文章

17、第七周-网络编程 - 协程概念介绍、协程gevent模块并发爬网页

协程,又称微线程,纤程.什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈.因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置. 协程的好处: 无需线程上下文切换的开销 无需原子操作锁定及同步的开销(注解:"原子操作(atomic operation)是不需要synchr

6、第七周-网络编程-继承式多线程

Python threading模块介绍,threading 是 Python 高级别的多线程模块. threading 模块的函数 active_count() 当前活动的 Thread 对象个数 current_thread() 返回当前 Thread 对象 get_ident() 返回当前线程 enumerater() 返回当前活动 Thread 对象列表 main_thread() 返回主 Thread 对象 settrace(func) 为所有线程设置一个 trace 函数 setpr

8、第七周-网络编程-GIL锁介绍

什么是全局解释器锁GIL Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即同一时刻,只有一个线程在解释器中运行.对Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行. 在多线程环境中,Python 虚拟机按以下方式执行: 1. 设置GIL2. 切换到一个线程去运行3. 运行:    a. 指定数量的字节码指令,或者 b. 线

线程中的信号量和事件

# 线程中的信号量 # 和进程中的信号量概念一样,创建好信号量的深度后,同一时间只有n个线程可以访问被信号量保护的代码 # 同一时间只有4个线程可以访问被信号量保护的代码 # import time # from threading import Semaphore, Thread # # def func(sem, a, b): # sem.acquire() # time.sleep(1) # print(a + b) # sem.release() # # if __name__ == '

asp网络编程:ASP中实现分页显示的七种武器

在微软的ASP编程体系中,ADO对象的建立,使得从网页访问数据库成为一件易事,特别是ADO的Recordset对象使得控制数据的输出显示更为方便.自由.而在Visual InterDev6.0(以下简称VI6.0)中,由于Script Object Model(以下简称SOM).Design-Time Control(以下简称DTC)以及Data Environment Object Model(以下简称DEOM)等对象模型的引入,使网页对数据库的访问设计显得更为方便. 因为主题方面的原因,关于

Java网络编程 线程

线程作用 当服务器需要大量并发连接的时候,一般使用轻量级的线程来处理大量的连接,而不是重量级的进程.线程在资源使用上更宽松,因为它们会共享内存.使用线程来代替进程,可以再让你的服务器性能提升三倍.再结合使用可重用的线程池,在同样的硬件和网络连接下,服务器的运行可以快9倍多!采用多线程设计设计会更容易,可以将程序分解为多个线程,分别执行独立的操作. 由于现代虚拟机和操作系统中线程可以提供很高的性能,而且构建基于线程的服务器相对简单,所以开始时总会考虑采用基于线程的设计.如果确实遇到麻烦,应该考虑将

python第七周-面向对象编程进阶

申明:本文内容主要转自Alex老师的博客,仅供学习记录! 静态方法 只是名义上归类管理,实际上在静态方法里访问不了类实例中的任何属性 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法 1 clas

python网络编程--线程(锁,GIL锁,守护线程)

1.线程 1.进程与线程 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率.很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上: 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了. 进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行. 如果这两个缺点理解比较困难的话,举个现实的例子也许你就清楚

第84节:Java中的网络编程(中)

实现客户端和服务端的通信: 客户端需要的操作,创建socket,明确地址和端口,进行键盘录入,获取需要的数据,然后将录入的数据发送给服务端,为socket输出流,然后进行读取服务端发送回来的大写数据,为socket读取流,最后进行客户端显示器的显示,进行读写操作,关闭资源. 网络编程TCP客户端 package com.dashucoding.tcp3; import java.io.BufferedReader; import java.io.BufferedWriter; import ja