信号量

经典同步问题之生产者消费者问题

拥有回忆 提交于 2020-03-09 18:18:58
本文来自个人博客: https://dunkwan.cn 文章目录 Classic Problem of Synchronization(经典同步问题) The Bounded-Buffer Problem(有限缓冲问题) The Producer-Consumer Problem(生产者消费者问题) The Buffer The Producer and Consumer Threads Pthreads Thread Creation and Synchronization Classic Problem of Synchronization(经典同步问题) 在这个部分,我们要讲述大量同步问题,像一大类并发控制问题的例子。对于测试几乎每一个最新提出的同步主题,这些问题都有被用到。在我们的这类问题的解决方案中,因为同步信号量是一种解决该问题的传统方式,所以我们使用同步信号量。然而,这些解决方案的具体实现可能在二元信号量的地方使用互斥锁。 while ( true ) { . . . /* produce an item an next_produced */ . . . wait ( empty ) ; wait ( mutex ) ; . . . /* add next_produced to the buffer */ . . . signal ( mutex ) ;

linux进程间的那些事儿

北城以北 提交于 2020-03-09 16:25:23
写这篇文章之前,我对linux的进程间通讯还是有些畏惧的,不过看了一些其它文章之后,觉得linux进程间远比我学到的要难得多,首先来说,linux下线程的概念被淡化了,线程又名轻量级进程。线程机制是现代编程技术中常用的一种抽象,提供了在同一程序中共享内存地址控件的一组线程。这些线程可以共享打开的文件和其它资源。线程机制支持并发程序涉及技术,可以保证真正并行处理。linux实现线程的机制非常独特,从内核的角度来说,没有线程这个概念,把所有线程当成进程来实现,内核并没有准备特别的数据结构来表示线程。相反,线程仅仅被视为一个与其它进程共享某些资源的进程,每个线程都拥有唯一率属于自己的task_struct,所以在内核中,看起来像一个普通的进程(只是该级才能哼和其它一些进程共享某些资源,如地址空间). 在windows或是sun solaris等操作系统中,提供了专门支持线程的机制,线程被抽象成一种耗费较少资源,执行迅速的单元。而对于linux来说,它只是一种进程间共享资源的手段。linux线程的创建和普通进程创建类似,只不过在调用clone的时候需要传递一些参数来指明需要共享的资源 clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND,0); 而一个普通的fork实现 clone(SIGCHLD,0) 而vfork的实现是 clone

并发工具——Semaphore

心不动则不痛 提交于 2020-03-08 18:24:18
Semaphore的使用和操作系统中的信号量的使用差不多,可以类比去理解。 Semaphore用于限制可以访问某些资源(物理或逻辑的)的线程数目,他维护了一个许可证集合,有多少资源需要限制就维护多少许可证集合,假如这里有N个资源,那就对应于N个许可证,同一时刻也只能有N个线程访问。一个线程获取许可证就调用acquire方法,用完了释放资源就调用release方法。 停车场案例代码实现: public class CarDemo { public static void main(String[] args) { //创建Semaphore Semaphore sp=new Semaphore(5); Thread[] car=new Thread[10]; for (int i = 0; i < 10; i++) { car[i]=new Thread(()->{ //请求许可 try { sp.acquire(); System.out.println(Thread.currentThread().getName()+"可以进停车场"); } catch (InterruptedException e) { e.printStackTrace(); } //使用资源 try { int val= new Random().nextInt(10); TimeUnit.SECONDS

操作系统 200314

给你一囗甜甜゛ 提交于 2020-03-08 11:34:39
1. 互斥和同步的关系? 指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 指在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。 实现同步和互斥的方式: 临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 互斥量:为协调共同对一个共享资源的单独访问而设计的。 信号量:为控制一个具有有限数量用户资源而设计。 事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 2. 死锁产生的条件? 互斥条件 (Mutual exclusion):资源不能被共享,只能由一个进程使用。 请求与保持条件 (Hold and wait):已经得到资源的进程可以再次申请新的资源。 非抢占条件 (No pre-emption)

第十二章 并发编程

心已入冬 提交于 2020-03-08 09:38:10
第十二章 并发编程 1、并发:逻辑控制流在时间上重叠 2、并发程序:使用应用级并发的应用程序称为并发程序。 3、三种基本的构造并发程序的方法: 进程,用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制。 I/O多路复用,应用程序在一个进程的上下文中显式的调度控制流。逻辑流被模型化为状态机。 线程,运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。 12.1 基于进程的并发编程 构造并发服务器的自然方法就是,在父进程中接受客户端连接请求,然后创建一个 新的子进程 来为每个新客户端提供服务。 基于进程的并发echo服务器的重点内容 (1)需要一个SIGCHLD处理程序,来 回收 僵死子进程的资源。 (2)父子进程 必须关闭 各自的connfd拷贝。对父进程尤为重要,以 避免存储器泄露 。 (3)套接字的文件表表项中的引用计数,直到父子进程的connfd都关闭了,到客户端的连接才会终止。 注意:进程的模型: 共享文件表 ,但不是共享用户地址空间。 优点:一个进程不可能不小心覆盖两个进程的虚拟存储器。 缺点:独立的地址空间使得进程共享状态信息变得更加困难。进程控制和IPC的开销很高。 Unix IPC 是指所有允许进程和同一台主机上其他进程 进行通信 的技术,包括管道、先进先出(FIFO)、系统V共享存储器,以及系统V信号量。 12.2 基于I

封装一个信号量集操作函数的工具

青春壹個敷衍的年華 提交于 2020-03-08 07:06:00
信号量的概念参见 这里 。 与消息队列和共享内存一样,信号量集也有自己的数据结构: struct semid_ds { struct ipc_perm sem_perm; /* Ownership and permissions */ time_t sem_otime; /* Last semop time */ time_t sem_ctime; /* Last change time */ unsigned short sem_nsems; /* No. of semaphores in set */ }; 同样地,第一个条目也是共有的ipc 对象内核结构,剩下的是私有成员。 Each semaphore in a semaphore set has the following associated values: unsigned short semval; /* semaphore value */ unsigned short semzcnt; /* # waiting for zero */ unsigned short semncnt; /* # waiting for increase */ pid_t sempid; /* process that did last op */ 即每一个在信号量集中的信号量都有上述4个相关的变量。 1、semval

Linux系统编程之信号量

你说的曾经没有我的故事 提交于 2020-03-07 02:11:53
原理: 1、信号量的概念 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞。 PV原语是对信号量的操作,一次P操作使信号量sem减1,一次V操作使信号量sem加1。 信号量主要用于进程或线程间的同步和互斥这两种典型情况。 (1)若用于互斥,几个进程(或线程)往往只设置一个信号量。 (2)若用于同步操作,往往会设置多个信号量,并且安排不同的初始值,来实现它们之间的执行顺序。 信号量用于互斥 信号量用于同步 例题1 :信号量实现互斥功能,模拟打印机 # include <stdio.h> # include <pthread.h> # include <unistd.h> # include <semaphore.h> sem_t sem ; void printer ( char * str ) { sem_wait ( & sem ) ; while ( * str ) { putchar ( * str ) ; fflush ( stdout ) ; str ++ ; sleep ( 1 ) ; } sem_post ( & sem ) ; } void * thread_fun1 ( void * arg ) {

7、uCOS-Ⅱ 信号量

时光怂恿深爱的人放手 提交于 2020-03-05 23:06:06
1、“信号量”为操作系统用于处理临界区问题和实现进程间同步提供了一种有效的机制。 在很多操作系统原理书中都提到了信号量的概念,常用P操作与V操作来表明信号量的行为。 PV操作的伪代码如下: 设s为一整数型变量: P操作:while( s==0); s--; V操作:s++ 2、例程代码 1 /***************************************************************************************************************************** 2 * 3 * 文件名称:main.c 4 * 文件功能:主函数 5 * 文件说明:无 6 * 7 *****************************************************************************************************************************/ 8 /********************************************************** 9 * 10 * 头文件声明 11 * 12 **********************************************************/ 13 14

L17 信号量临界区保护

痞子三分冷 提交于 2020-02-29 19:32:00
为什么要保护信号量和临界区? 在现实中如何保护信号量和临界区? empty = -1:的含义? 表示有一个进程正在睡眠 为什么要保护? 进程中存在一种调度,使得信号量引发错误。所以要保护! 怎么保护信号量? 要上锁 什么是临界区? 当一个进程在进入一段代码时,另外一个进程不能进入对应的修改信号的代码。所以出现了保护修改信号量的临界区。 临界区代码的保护原则? 临界区怎样设计呢? 方法一 用一个轮换法试试? 这种方法满足互斥要求,但是P 0 执行之后,没有进程P 1 了,P 0 无法继续执行。所以不行!!! 方法二 标记法: 每一个进程都有一个标记,进入的时候把自己的标记标为true,判断 互斥吗? 互斥,P0进入时:flag[0] = true;flag[1] = false; P1进入时:flag[1] = true;flag[0] = false; 但是有问题 如果按照(1)(2)(3)(4)执行,谁都进不去临界区 还是不行,怎么做呢? 方法三 改一下, 非对称标记 进入临界区Peterson算法(这个算法真聪明) 结合了标记和轮转两种思想:(值日加标记·) 多进程怎么办?—面包店算法(不懂) 临界区保护另外一种解法:关中断,和开中断 也存在问题,当出现多CPU时,一个CPU关闭中断,另一个CPU仍然可以执行P i 进程,这种策略不好使,但是在单CPU种很方便。

6种Linux进程间的通信方式

淺唱寂寞╮ 提交于 2020-02-29 11:32:34
进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放。可以认为进程是一个程序的一次执行过程。 进程通信的概念 进程用户空间是相互独立的,一般而言是不能相互访问的。但很多情况下进程间需要互相通信,来完成系统的某项功能。进程通过与内核及其它进程之间的互相通信来协调它们的行为。 进程通信的应用场景 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。 资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。 进程通信的方式 1.管道 管道分为有名管道和无名管道 无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系。无明管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端