生产者消费者问题

Java基础常见面试题最后十题

两盒软妹~` 提交于 2020-02-24 20:15:48
1.为什么等待(wait())和通知(notify())是在 Object 类而不是 Thread 中声明的? 生产者-消费者问题代码实现 ①.生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 ②.解决办法:要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。 void notify() 唤醒在此对象监视器上等待的单个线程 void notifyAll()

第 10 章 python进程与多进程

那年仲夏 提交于 2020-02-24 13:37:07
一、背景知识 顾明思义,进程即正在执行的一个过程,进程是对正在云的程序的一个抽象。 进程的概念起源与操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一,操作系统的其他所有内容都是围绕进程的概念展开的。 ps:即使可以利用的cpu只有一个(早期的计算机确实如此),也能保证支持(伪)并发的能力,将一个单独的cpu变成多个虚拟的cpu(多道技术:时间多路复用和空间多路复用+硬件上支持隔离),没有进程的抽象,现代计算机将不复存在。 必备的理论基础: 1 #一 操作系统的作用: 2 1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口 3 2:管理、调度进程,并且将多个进程对硬件的竞争变得有序 4 5 #二 多道技术: 6 1.产生背景:针对单核,实现并发 7 ps: 8 现在的主机一般是多核,那么每个核都会利用多道技术 9 有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个 10 cpu中的任意一个,具体由操作系统调度算法决定。 11 12 2.空间上的复用:如内存中同时有多道程序 13 3.时间上的复用:复用一个cpu的时间片 14 强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样 15 才能保证下次切换回来时,能基于上次切走的位置继续运行 二、python并发编程之进程 1、进程

python学习笔记-进程线程

你。 提交于 2020-02-23 19:10:48
1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。 在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。 2.什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 3.有了进程为什么还要线程? 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上: 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。 进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。 例如,我们在使用qq聊天,

生产者-消费者问题

不羁岁月 提交于 2020-02-21 03:41:56
生产者消费者问题 ,也称 有限缓冲问题 ,是一个 多线程 同步 问题的经典案例。   该问题描述了两个共享固定大小 缓冲区 的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。   与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。   要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。   通常采用 进程间通信 的方法解决该问题,常用的方法有 信号灯法 [1] 等。如果解决方法不够完善,则容易出现 死锁 的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。 信号灯方法   信号灯可以避免上述唤醒指令不起作用的情况。该方法使用了两个信号灯,fillCount 和 emptyCount。 fillCount 用于记录缓冲区中将被读取的数据项数 (实际上就是有多少数据项在缓冲区里), emptyCount 用于记录缓冲区中空闲空间数 。当有新数据项被放入缓冲区时,fillCount 增加

进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

三世轮回 提交于 2020-02-19 07:11:28
一、paramiko模块 他是什么东西?   paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。 先来个实例: 1 import paramiko 2 # 创建SSH对象 3 ssh = paramiko.SSHClient() 4 5 # 允许连接不在know_hosts文件中的主机 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 7 # 连接服务器 8 ssh.connect(hostname='10.0.0.31', port=52113, username='root', password='123456') 9 # 执行命令 10 stdin, stdout, stderr = ssh.exec_command('df') 11 # 获取命令结果 12 res,err = stdout.read(),stderr.read() 13 result = res if res else err 14 15 print(result.decode()) 16 17 # 关闭连接 18 ssh.close() 有些机智的少年会突然想到,如果我想做信任呢??我的秘钥怎么用在里面呢? 同样机智的我想到了下面的方法: 1 import

kafka核心概念

女生的网名这么多〃 提交于 2020-02-17 23:12:18
目录 1.kafka中涉及的名词 2.kafka功能 3.kafka中的消息模型 4.大概流程 1.kafka中涉及的名词 消息记录(record): 由一个key,一个value和一个时间戳构成,消息最终存储在主题下的分区中, 记录在生产者中称为生产者记录(ProducerRecord), 在消费者中称为消费者记录(ConsumerRecord),Kafka集群保持所有的消息,直到它们过期, 无论消息是否被消费了,在一个可配置的时间段内,Kafka集群保留所有发布的消息,不管这些消息有没有被消费。比如,如果消息的保存策略被设置为2天,那么在一个消息被发布的两天时间内,它都是可以被消费的。之后它将被丢弃以释放空间。Kafka的性能是和数据量无关的常量级的,所以保留太多的数据并不是问题。 生产者(producer): 生产者用于发布(send)消息 消费者(consumer): 消费者用于订阅(subscribe)消息 消费者组(consumer group): 相同的group.id的消费者将视为同一个消费者组, 每个消费者都需要设置一个组id, 每条消息只能被 consumer group 中的一个 Consumer 消费,但可以被多个 consumer group 消费 主题(topic): 消息的一种逻辑分组,用于对消息分门别类,每一类消息称之为一个主题

day 31-1 守护进程、互斥锁、队列、生产消费模型

二次信任 提交于 2020-02-17 01:14:58
守护进程 关于守护进程需要强调两点 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children from multiprocessing import Process import time def foo(): pass def run(): print('this is 子进程') time.sleep(3) p1 = Process(target=foo,) # AssertionError: daemonic processes are not allowed to have children p1.start() if __name__ == '__main__': p = Process(target=run,) p.daemon = True # 守护进程要主进程执行完毕前开启 p.start() p.join() print('主进程') 互斥锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱, 主要参数: from multiprocessing import Process, Lock  

Linux 生产者消费者模型

只愿长相守 提交于 2020-02-16 23:29:18
生产者消费者模型 生产者消费者模型是非常常用的模型。本文用的是互斥和同步实现生产者消费者模型。 下面来介绍是如何实现生产者消费者模型 1 .在模型(生产者消费者模型)中,我们的临界资源不再是单单的一个数了,而是存储多个元素的队列,我们用的是STL中的queue容器。 2 .模型中有生产者和消费者。 生产者:网队列中放数据。 消费者:从队列中拿数据。 如果我们仅仅只用queue当做是模型的临界资源是不满足于我们当前的这种多个消费者、生产者的情况的。因为有可能会造成程序的二义性,并且不能保证消费者和生产者访问资源的合理性。因此就需要用同步和互斥来解决这种问题。 所以模型中的queue必须是线程安全的。 1.互斥:是解决程序的二义性。保证只有一个执行流访问一个结点资源。 2.同步:保证生产者与消费者访问资源的合理性,以及保证生产者不会一直生产,导致进程被操作系统强杀。 (因为如果没有条件变量,生产者有可能会一直生产资源,让队列不断地扩容,操作系统会认为我们这个程序有可能有内存泄漏的风险,最终进程会被操作系统强杀。) 所以我们queue的资源要定义为定量的,这样当队列满的时候生产者则进入PCB等待队列中等待,唤醒消费者来消费。 总而言之,生产者消费者模型的实现是靠: 一个场所(queue),两个角色(生产者、消费者),三种关系(消费者与消费者互斥、生产者与生产者互斥、生产者和消费者互斥)

java多线程回顾4:线程通信

南笙酒味 提交于 2020-02-14 23:42:04
1 、线程的协调运行 线程的协调运行有一个经典案例,即生产者和消费者问题。 假设有一个货架,生产者往货架上放货物,消费者从货架上取货物。 为了方便讲解,制定一个规则,生产者每放上一个货物,消费者就得取走一个货物。不允许连续放两次,也不允许连续取两次。 为了实现这个功能,可以使用 wait() 、 notify() 和 notifyAll() 三个方法。注意,这三个方法不属于 Thread 类,而是属于 Object 类,且必须由同步监视器对象调用。详细用法如下: <![if !supportLists]> Ø <![endif]> 对于使用 synchronized 修饰的同步方法,因为默认实例 (this) 就是同步监视器对象,所以可以在同步方法中直接调用这三个方法。 <![if !supportLists]> Ø <![endif]> 对于使用 synchronized 修饰的同步代码块,同步监视器对象是 synchronized 后括号里的对象,必须使用该对象调用这三个方法 这三个方法的作用如下: <![if !supportLists]> Ø <![endif]> wait() :使当前线程等待,直到其他线程调用该同步监视器的 notify() 或 notifyAll() 来唤醒该线程。调用 wait() 的当前线程会释放对该同步监视器的锁定。 <![if

Posix信号量

血红的双手。 提交于 2020-02-13 00:02:42
1、概述   信号量(semaphore)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。Posix信号量分为有名信号量和无名信号量(也叫基于内存的信号量)。 2、Posix有名信号量   有名信号量既可以用于线程间的同步也可以用于进程间的同步。 1)由sem_open来创建一个新的信号量或打开一个已存在的信号量。其格式为: sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value); 返回:若成功则为指向信号量的指针,若出错则为SEM_FAILED 其中,第三、四个参数可以没有,主要看第二个参数如何选取。 oflag参数:可以是0、O_CREAT或O_CREAT|O_EXCL。如果指定O_CREAT标志而没有指定O_EXCL,那么只有当所需的信号量尚未存在时才初始化它。但是如果所需的信号量已经存在也不会出错。 但是如果在所需的信号量存在的情况下指定O_CREAT|O_EXCL却会报错。 mode参数:指定权限位。 value参数:指定信号量的初始值