信号量

信号量

时光怂恿深爱的人放手 提交于 2019-11-27 08:09:09
# 信号量可能在不同领域对应不同的知识点 ''' 互斥锁:代表一个坑位 信号量:代表一个公共厕所,有多个坑位 ''' from threading import Semaphore,Thread import time import random sm = Semaphore(4) # 制造一个有五个坑位的厕所 def task(name): sm.acquire() print('%s 抢到了坑位' % name) time.sleep(random.randint(1, 3)) sm.release() if __name__ == '__main__': for i in range(20): t = Thread(target=task, args=(i,)) t.start() 来源: https://www.cnblogs.com/asdaa/p/11353319.html

python并发——信号量

拈花ヽ惹草 提交于 2019-11-27 07:31:27
信号量通常用于保护数量有限的资源,例如数据库服务器。在资源数量固定的任何情况下,都应该使用有界信号量。在生成任何工作线程前,应该在主线程中初始化信号量。 工作线程生成后,当需要连接服务器时,这些线程将调用信号量的 acquire 和 release 方法: 使用有界信号量能减少这种编程错误:信号量的释放次数多于其请求次数。 from threading import BoundedSemaphore maxconnections = 5 pool_sema = BoundedSemaphore(value=maxconnections) with pool_sema: conn = connectdb() try: do_some() finally: conn.close() 来源: https://www.cnblogs.com/wangbin2188/p/11937111.html

进程、线程以及IPC---linux

牧云@^-^@ 提交于 2019-11-27 07:08:05
进程(标识pid) <unistd.h> <sys/types.h> 资源集合:内存 文件 时间片 协处理器 完全复制:复制前执行什么,复制后执行什么 fork() 系统调用函数fork()是创建一个新进程的唯一方式 一次复制一个进程 返回值-1,创建失败; 返回值 0,进入子进程; 一般来说,fork()成功之后,父进程与子进程的执行顺序是不确定的。这取决于内核所使用的调度算法,如果要求父子进程相互同步,则要求某种形式的进程间通信。 vfork() 执行次序: fork():对父子进程的调度室由调度器决定的; vfork():是先调用子进程,等子进程的exit(1)被调用后,再调用父进程; 对数据段的影响: fork():父子进程不共享一段地址空间,修改子进程,父进程的内容并不会受影响。 vfork():在子进程调用exit之前,它在父进程的空间中运行,也就是说会更改父进程的数据段、栈和堆。即共享代码区和数据区,且地址和内容都是一样的。 IPC机制(6种) 管道(Pipe)及有名管道(named pipe): 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信; 信号(Signal): 信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身

RTT-信号量随笔

谁说我不能喝 提交于 2019-11-27 07:05:02
信号量有点类似全局变量标志,但是应用有差别。 struct rt_semaphore sem_test; 初始化一个静态信号量 if(rt_sem_init(&sem_test,"test",0,RT_IPC_FLAG_FIFO)==RT_EOK) { UsartPrintf(USART1, "init sem_test is OK\r\n"); } else { UsartPrintf(USART1, "init sem_test is fail\r\n"); } 放一个信号量 rt_sem_release(&sem_test); 识别信号量 处理任务 if(rt_sem_trytake(&sem_test)==RT_EOK) { UsartPrintf(USART1, "get sem_test is ok\r\n"); } 来源: https://blog.csdn.net/u012210286/article/details/99538885

同步和异步的区别

谁都会走 提交于 2019-11-27 06:00:54
同步和异步的概念对于很多人来说是一个模糊的概念,是一种似乎只能意会不能言传的东西。其实我们的生活中存在着很多同步异步的例子。比如:你叫我去吃饭,我听到了就立刻和你去吃饭,如果我们有听到,你就会一直叫我,直到我听见和你一起去吃饭,这个过程叫同步;异步过程指你叫我去吃饭,然后你就去吃饭了,而不管我是否和你一起去吃饭。而我得到消息后可能立即就走,也可能过段时间再走。如果我请你吃饭,就是同步,如果你请我吃饭就用异步,这样你比较省钱。哈哈哈。。。 方法/步骤: 在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。 而我们平时经常讨论的同步问题多发生在多线程环境中的数据共享问题。即当多个线程需要访问同一个资源时,它们需要以某种顺序来确保该资源在某一特定时刻只能被一个线程所访问,如果使用异步,程序的运行结果将不可预料。因此,在这种情况下,就必须对数据进行同步,即限制只能有一个进程访问资源,其他线程必须等待。 实现同步的机制主要有临界区、互斥、信号量和事件 **临界区:**通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问

进程间通信方式总结

一个人想着一个人 提交于 2019-11-27 03:53:33
如图片显示异常请前往掘金查看: https://juejin.im/post/5d515c7551882511ed7c273c 前言 进程间的通信方式,其实我们一直在用它,但是我们都不会去注意它。如果碰到面试官问你知道多少种进程间的通信方式,估计很多人都会有点懵。今天我们就来总结下进程间的通信方式有哪些。 管道 管道,英文为pipe。这是一个我们在学习Linux命令行的时候就会引入的一个很重要的概念。它的发明人是道格拉斯.麦克罗伊,这位也是UNIX上早期shell的发明人。他在发明了shell之后,发现系统操作执行命令的时候,经常有需求要将一个程序的输出交给另一个程序进行处理,也因此,管道应运而生了。 管道可以分为两类:匿名管道和命名管道。 常见的Linux命令 "|" 其实就是匿名管道,表示把一个进程的输出传输到另外一个进程,如: echo "Happyjava" | awk -F 'j' '{print $2}' # 输出 ava 另外,我们可以通过 mkfifo <pipename> 命令创建一个命名管道,如: mkfifo pipe 一个进程往管道输入数据,则会阻塞等待别的进程从管道读取数据: 如果我另外一个窗口没有执行 cat < pipe 命令,则左边的窗口(echo 'Happyjava' > pipe)会一直阻塞。 消息队列 注意,此消息队列不是我们常用的MQ

Semaphore的简介及应用场景

非 Y 不嫁゛ 提交于 2019-11-27 03:16:34
Semaphore 是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。 常用函数: 信号量的构造函数 非公平: public Semaphore(int permits);//permits就是允许同时运行的线程数目 公平(获得锁的顺序与线程启动顺序有关): public Semaphore(int permits,boolean fair);//permits就是允许同时运行的线程数目 创建一个信号量 Semaphore semaphore = new Semaphore(2); 从信号量中获取一个许可 semaphore.acquire(); 释放一个许可(在释放许可之前,必须先获获得许可。) semaphore.release(); 尝试获取一个许可,若获取成功返回true,若获取失败返回false semaphore.tryAcquire(); 所有函数: // 创建具有给定的许可数和非公平的公平设置的 Semaphore。 Semaphore(int permits) // 创建具有给定的许可数和给定的公平设置的 Semaphore。 Semaphore(int permits, boolean fair) // 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 void acquire() // 从此信号量获取给定数目的许可

理解PV操作和信号量

荒凉一梦 提交于 2019-11-27 01:16:00
对于信号量,可以认为是一个仓库,有两个概念,容量和当前的货物个数。 P操作从仓库拿货,如果仓库中没有货,线程一直等待,直到V操作,往仓库里添加了货物,为了避免P操作一直等待下去,会有一个超时时间。 V操作往仓库送货,如果仓库满了,线程等待,直到有P操作,从仓库中拿走货物,有空的位置。 创建信号量,设置容量,先有V操作,才能P操作。 P操作:货物个数减1,减过之后,货物个数大于等于0,说明已经拿到货物,线程继续。否者线程阻塞。 V操作:货物个数加1,加过之后,货物个数小于等于容量,说明添加成功,线程继续。否者线程阻塞。 信号量:0≤ 信号量≤容量 ,取值 表示当前可以使用的货物;    信号量<0 , 取值 表示当前等待使用货物的线程; 信号量>容量 , 信号量-容量 表示当前等待添加货物的线程。 通常,信号量的容量设置很大,可以一直V操作,不会阻塞,但是P操作的时候,很可能阻塞。 当容量为1,也就是互斥,执行流程必定是V操作,P操作,V操作,P操作... 信号量如何做到线程同步? 可以认为信号量关联一组线程,保存一个指针,指向线程数组的首地址。比如当前信号量为-1,进行P操作,信号量为-2,说明没有拿到货物,线程等待,取值为-2,说明有两个线程等待那货物。这个时候,其他线程进行V操作,信号量加1,为-1,信号量通知等待的线程中,第一个线程继续执行,第二个线程继续等待。 也就是说

同步 互斥体和信号量

二次信任 提交于 2019-11-27 01:09:39
1、互斥体和信号量都是为了实现同步,但是二者解决的问题不一样,也就是说应用场景不一样。 2、互斥体通过加锁,对于共享的资源,大家排队,依次去访问,一个一个来。也就是说,任何时刻只有一个线程访问,其他的线程等待。 3、互斥体加锁存在的问题:无法控制线程的访问顺序。考虑两个线程A,B,访问顺序可能是A-B,也可能是B-A,就要看谁先加锁。 4、考虑下面的场景,生产者/消费者模式,假定A是生产者,B是消费者,生产一个,消费一个,循环下去,这样就要求访问顺序必须是A-B-A-B... 5、怎么解决这个问题?   使用信号量,初始化,信号量的容量是1,可用资源为0。A进行V操作,资源加1,B进行P操作,资源减1。A进行V操作的时候,如果可用资源为1(容量满了),必须等待,直到B消费掉资源。B进行P操作的时候,如果可用资源为0(没有资源可用),必须等待,直到A生产出一个资源。通过这种方式控制线程访问顺序。 6、这里可以看出二者的区别:   a、互斥体:大家排队,一个一个来。信号量:控制访问顺序,当前线程检查条件,条件不满足,等待其他的线程去操作,使条件满足。   b、对互斥体加锁,必须是谁加锁谁释放。而对信号量PV操作,是不同线程之间可以进行成对的PV操作。   c、可以使用信号量的PV操作来模拟互斥体的加锁,信号量容量为1,可用资源为1,每个线程都先P操作,do sth ,再V操作

Linux内核同步方法

百般思念 提交于 2019-11-27 00:43:34
1、原子操作,是其它同步方法的基础。 2、自旋锁,线程试图获取一个已经被别人持有的自旋锁,当前线程处于忙等待,占用cpu资源。 3、读写自旋锁,根据通用性和针对性的特点,普通自旋锁在特定场景下的表现会退化。因此,提供了读写自旋锁,读锁可以加读锁,不能加写锁,写锁不能加任何锁。 4、需要注意的几项:   普通自旋锁是不能递归的。读锁可以递归,写锁也不能递归。   表面上锁的是代码,实际上锁的是共享数据。   使用读写锁的时候,需要注意,读锁可以加读锁,多个线程都占用读锁,必须所有的线程都释放,才能加上写锁,这往往会导致写锁长时间处于饥饿状态。 5、自旋锁存在的问题,线程试图获取一个已经被别人持有的自旋锁,当前线程处于忙等待,占用cpu资源。怎么解决这个问题?   使用信号量,信号量是一种睡眠锁。一个任务试图获取被别人占有的信号量,信号量会将其推进一个等待队列,让其睡眠,当请求的信号量被释放,处于等待队列的任务被唤醒,并获得信号量。 6、需要注意的是,信号量是一种睡眠锁,但它本身也会带有开销,上下文切换,被阻塞的线程要换出换入,也即是说让其睡眠并唤醒它,花费一定的开销。如果每个线程锁的时间很短,一般使用自旋锁,忙等待的时间也很短。如果锁的时间长,使用信号量。 7、相比自旋锁,信号量还有更广泛的用处,使用PV操作不仅能保护共享资源,还能够控制同时访问的数量,还能够控制访问顺序。对于锁