展开

关键词

线程通信机制—共享内存:消息传递

目前有两种方式: 1、共享内存 2、消息传递(actor 模型) 共享内存 共享内存这种方式比较常见,我们经常会设置一个共享变量。然后多个线程去操作同一个共享变量。从而达到线程通讯的目的。 例如,我们使用多个线程去执行页面抓取任务,我们可以使用一个共享变量count来记录任务完成的数量。每当一个线程完成抓取任务,会在原来的count上执行加1操作。 这样每个线程都可以通过获取这个count变量来获得当前任务的完成情况。当然必须要考虑的是共享变量的同步问题,这也共享内存容易出错的原因所在。 这种通讯模型中,不同的线程之间是没有直接联系的。 这种模型看起来比共享内存模型要复杂。但是一旦碰到复杂业务的话,actor模型的优势就体现出来了。我们还是以刚才多线程抓取网站为例子看一下在这种模型下如何去解决。 最后让我们来总结一下这两种通讯模式: 并发模型 通信机制 同步机制 共享内存 线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。 同步是显式进行的。

6320

nginx共享内存共享内存的实现

而ngx_shared_memory_add不会马上创建一个共享内存,它是先登记一下共享内存的使用信息,比如名称、大小等,然后在进程初始化的时候再进行共享内存的创建初始化。 如果此共享内存不存在,则添加一个新的ngx_shm_zone_t 添加完后,会返回ngx_shm_zone_t,然后再设置init函数data数据 // tag一般为某一模块 ngx_shm_zone_t = 0) { continue; } // 如果新的共享内存的大小原有的共享内存大小相同,就不需要重新添加了 // 注意,如果新配置的共享内存大小老的共享内存大小不一样,那老的共享内存大小就被释放掉了,所以这点我们要特别注意 ngx_shm_free(&oshm_zone 接下来,在我们的init函数里面,将共享内存强制转换成slab,以后,我们对共享内存的分配释放,就可以通过这个slab来实现了(可以参考我前一篇文章中共享内存的使用相关的分析)。

1.7K30
  • 广告
    关闭

    90+款云产品免费体验

    提供包括云服务器,云数据库在内的90+款云计算产品。打造一站式的云产品试用服务,助力开发者和企业零门槛上云。

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Java线程内存模型

    2.内存之间的交互操作 2.1 Lock (锁定): 把一变量标识为一条线程独占的状态 2.2 unlock (解锁) : 把处于锁定状态的变量释放出来 2.3 read (读取) : 把一个变量从主内存加载到工作内存 2.4 load (载入) : 把工作内存中的变量值复制到变量副本当中 2.5 use (使用) : 将值传递给工作引擎 2.6 assign (赋值) : 把从执行引擎接收到的值传递给工作内存的变量 2.7 store (存储) : 把工作变量当中的值传送到主内存当中,之后可以进行write操作 2.8 write (写入) : 把操作完成之后的值写到主内存的对应变量当中 3.volatile类型变量的特殊规则 ,防止其他线程抢占式串行执行 4.对于long和double类型的特殊规则 Java内存模型当中上述2.1~2.8的所有操作都是要求要具备原子性的,但是对于64位的数据类型long和double来说却是需要分割成来此来进行操作的 5.Java线程调度 协同式调度 优点是线程顺序执行,每个线程执行完成之后通知下一个线程执行,线程的切换时可知的 缺点是一旦有一条线程的代码出现问题,一直不通知下一个线程,那么就可能导致线程的阻塞问题

    19420

    线程共享变量的内存不可见性

    线程的开销 : 线程的创建和销毁 线程的上下文切换和调度 线程的同步 多线程内存模型: 线程独有的工作内存(线程缓存用于提高效率)---------所有线程共享的主内存 线程读取在主内存的成员变量( 即共享变量)的过程: 线程的工作内存会去读取主内存的成员变量并保存副本 线程在工作内存中修改副本 将修改后的副本的值推送给主空间并改写主空间该成员变量的值 主空间成员变量修改后的值将不会主动推送给其他线程 , 这就造成了线程的工作内存共享变量的不同步 问题: 各个线程的工作内存不可见   即 A线程先读取共享变量a, B线程修改了共享变量a后为a`,推送给主内存并改写, 主内存不会推送给A线程,A和B的变量会不同步 工作内存中会主动去拉取主内存共享变量并创建其副本 工作内存中的副本修改后会推送给主内存改写共享变量 volatile 会使得主内存修改后的共享变量推送其他线程 内存不可见的本质 : 线程之间有互相独立的缓存区, 当多个线程共享数据进行操作时, 其操作彼此不可见 可以直接理解: 使用volatile之后该共享该变量线程不在工作内存缓存其副本, 所有线程对该变量的操作全是在主内存中完成

    28520

    java内存模型线程

    JMM规定了jvm有主内存(Main Memory)和工作内存(Working Memory) ,主内存存放程序中所有的类实例、静态数据等变量,是多个线程共享的,而工作内存存放的是该线程从主内存中拷贝过来的变量以及访问方法所取得的局部变量 ,是每个线程私有的其他线程不能访问,每个线程对变量的操作都是以先从主内存将其拷贝到工作内存再对其进行操作的方式进行,多个线程之间不能直接互相传递数据通信,只能通过共享变量来进行。 这些行为是不可分解的原子操作,在使用上相互依赖,read-load从主内存复制变量到当前工作内存,use-assign执行代码改变共享变量值,store-write用工作内存数据刷新主存相关内容。     0 线程a将工作内存中x加1,工作内存中x值变为1 线程a将x提交到主存,主存中i变为1 线程b将工作内存中y加1,工作内存中y值变为1 线程b将y提交到主存中,主存中i变为1    *单线程环境下, 如果用volatie声明了,读取主存副本到工作内存和同步i到主存的步骤,相当于是一个原子操作,因此是线程安全的。     volatile适合这种场景:一个变量被多个线程共享线程直接给这个变量赋值。

    52160

    JVM之内存模型线程

    内存工作内存 java内存模型规定了:所有的变量都存储在主内存中 每条线程还有自己的工作内存线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取,赋值)都必须在工作内存中进行 不同的线程之间也无法直接访问对方工作内存中的变量 线程间变量值的传递均需要通过主内存来完成:线程内存、工作内存三者关系如下所示: 这里所讲的主内存,工作内存前面讲的 java内存区域中的 前半句是指: 线程内表现为串行的语义,后半句是指:指令重排序现象和工作内存内存同步延迟现象; **volatile和 synchronized关键字保证了线程间操作的有序性:**volatile关键字本身就包含了禁止指令重排序的语义 java内存模型中定义的两项操作之间的偏序关系,如果说操作A 先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到, 影响包括 修改了内存共享变量的值,发送了消息,调用了方法等 线程的实现 线程是比进程更轻量级的调度执行单位: 线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址,文件IO等),又可以独立调度(线程是CPU 调度的基本单位)

    5910

    共享内存原理VCS监控采集实战

    二、共享内存原理 1、原理 在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个之对应的页表,负责将进程的虚拟地址物理地址进行映射,通过内存管理单元 但是,我们要确保一个进程在写的时候不能被读,因此我们使用信号量来实现同步互斥。 2、传统文件对比 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式, 因为进程可以直接读写内存,而不需要任何 数据的拷贝。 对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝 共享内存则只拷贝两次数据: 一次从输入文件到共享内存区,另一次从共享内存区到输出文件。 共享内存中的内容往往是在解除映 射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。

    31830

    POSIX共享内存

    如下图所示: image.png 共享内存也是一种IPC,它是目前可用IPC中最快的,它是使用方式是将同一个内存区映射到共享它的不同进程的地址空间中,这样这些进程间的通信就不再需要通过内核,只需对该共享内存区域进程操作就可以了 ,和其他IPC不同的是,共享内存的使用需要用户自己进行同步操作。 对shm_open创建的POSIX共享内存区对象进程内存映射,以供无亲缘进程间进行通信。 基于mmap的POSIX共享内存 上面介绍了通过内存映射文件进行进程间的通信的方式,现在要介绍的是通过POSIX共享内存区对象进行进程间的通信。 mode:用于设置创建的共享内存区对象的权限属性。

    78010

    C语言共享内存

    共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。 参考资料: 共享内存 linux进程间的通信(C): 共享内存 共享内存特点 共享内存是进程间共享数据最快的方法 一个进程向共享内存写入数据,共享这个内存区域的所有进程就可以立即看到其中的内容。 使用共享内存需要注意的是多进程之间对一个给定存储区访问的互斥 若一个进程正在向共享区写数据,则在它操作完成之前,其他的进程不应当去读、写这些数据。 , char *argv[]) { // 共享内存的shmid int shmid; // 共享内存的key key_t key; char *shmadd; shmadd = shmat(shmid, NULL, 0)) < 0) { perror("shmat error."); exit(-1); } // 拷贝共享数据到共享内存

    1.6K20

    Python - mmap 共享内存

    python的mmap库提供了共享内存的实践方案可以完成信息在内存间交互。 简介 共享内存 内存共享是两个不同的进程共享内存的意思:同一块物理内存被映射到两个进程的各自的进程地址空间。 os.O_SHORT_LIVED os.O_TEMPORARY O_CREAT一起创建临时文件 os.O_RANDOM 缓存优化,但不限制从磁盘中随机存取 os.O_SEQUENTIAL flags:MAP_PRIVATE:这段内存映射只有本进程可用;mmap.MAP_SHARED:将内存映射和其他进程共享,所有映射了同一文件的进程,都能够看到其中一个所做的更改; **prot:* 使用示例 写入数据进共享内存 import ctypes import mmap # 核心库 import os import struct import numpy as np # 创建内存映射文件句柄 buf.flush(0, 100) # 关闭 buf.close() 从共享内存中读取数据 import mmap import os import struct import cv2 import

    8830

    Android匿名共享内存

    ashmem的使用流程如下: 1.ashmem_create_region创建匿名共享内存区域,本质是调用open系统调用 2.ioctl设置共享内存的名字和大小,设置的名字为/dev/ashmem/ ,名字的存在就为了能够让其他人找到目标 3.mmap映射文件中的虚拟内存以及物理内存 4.直接对着这一块地址区域读写。 Binder的mmap时候已经通过伙伴系统绑定了物理页和虚拟内存之间的联系,而Ashmem则是通过缺页中断,调用相关的函数才进行绑定。 Ashmem就是打通一块大的内存通道方便进程之间通信大数据。而Binder更加倾向小规模的指令,并且这种指令有明确的方向和顺序,保证每一个指令的可靠性。

    9520

    unix共享内存要点

    2.随内核持续     *nix的共享内存有两套API:Posix和System V     两者的主要差别是共享内存的大小         1.Posix共享内存大小可通过函数ftruncate随时修改         2.System V共享内存大小在创建时就已经确定,而且最大值根据系统有所不同     Posix共享内存     #include <sys/mman.h>  (mmap,munmap mmap将句柄作为共享内存的底层支撑对象,映射到内存中,这样可以不通过read、write在进程之间共享内存。由此推测一下,在*nix的进程间传 递数据更加原始的方法是进程间读写一个文件。 V的共享内存有大小的限制,所以可考虑,使用共享内存数组来解决这个问。 虽然数组的大小即一个进程可以获取共享内存的数量也是有限制,但是可以缓解System V单个共享内存过小的问题。

    30650

    UNIX共享内存总结

    共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。 进程间通讯-生产者消费者模式     生产者进程和消费者进程通讯常使用共享内存,比如一个网络服务器,接入进程收到数据包后,直接写到共享内存中,并唤醒处理进程,处理进程从共享内存中读数据包,进行处理。 父子进程间通讯     由于fork产生的子进程和父进程不共享内存区,所以父子进程间的通讯也可以使用共享内存,以POSIX共享内存为例,父进程启动后使用MAP_SHARED建立内存映射,并返回指针ptr 比较好的解决办法是,由一个进程负责把配置文件加载到共享内存中,然后所有需要这份配置的进程只要使用这个共享内存即可。 【共享内存分类】 1. POSIX V共享内存区对象不同的是,SYSTEM V的共享内存区对象的大小是在调用shmget创建时固定下来的,而POSIX共享内存区大小可以在任何时刻通过ftruncate修改。

    1.1K40

    PHP共享内存

    在asp.net和java中都有共享内存,php除了可以使用Memcached等方式变通以外其实php也是支持共享内存的!

    13720

    unix共享内存要点

    2.随内核持续     *nix的共享内存有两套API:Posix和System V     两者的主要差别是共享内存的大小         1.Posix共享内存大小可通过函数ftruncate随时修改         2.System V共享内存大小在创建时就已经确定,而且最大值根据系统有所不同     Posix共享内存     #include <sys/mman.h>  (mmap,munmap mmap将句柄作为共享内存的底层支撑对象,映射到内存中,这样可以不通过read、write在进程之间共享内存。由此推测一下,在*nix的进程间传 递数据更加原始的方法是进程间读写一个文件。 V的共享内存有大小的限制,所以可考虑,使用共享内存数组来解决这个问。 虽然数组的大小即一个进程可以获取共享内存的数量也是有限制,但是可以缓解System V单个共享内存过小的问题。

    282100

    内存页面共享-KSM

    导读 本文适合有基本Linux内存管理概念的新手阅读,且本文旨在从工作流程和设计思想上介绍KSM,在涉及到源代码的地方,进行了部分删减,如果想详细了解KSM,推荐阅读源代码及源代码中的注释。 一、KSM概述 KSM的全称是 Kernel Samepage Merging,主要应用在虚拟化环境中,它允许内核通过合并内存页面来节省内存,从来可以增加虚拟机的并发数据。 SYSCALL_DEFINE3 在这里会进行一个预处理,如找到该内存区域的所有VMA,并调用 madvise_vma 进行进一步处理。 vma->vm_flags = new_flags; out: return error; } ksm_madvise 在这一步会找到 vma 所属进程(mm),并判断标记决定是否对页面进行共享 如果需要共享,调用 __ksm_enter()并传递当前 vma 所属的 mm 地址。

    53440

    一文详解共享内存-附带QT共享内存Demo实现

    2、共享内存通信的工作原理 在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个之对应的页表,负责将进程的虚拟地址物理地址进行映射,通过内存管理单元 这个attact的过程其实就相当于我们前面概念所说的,将进程的虚拟内存实际逻辑内存地址相对应的过程。 这时Write进程就可以向共享内存中写图片数据了。 其它进程如何读取图片呢? QSharedMemory提供了多个线程和进程对共享内存段的访问。它还为单个线程或进程提供了一种锁定内存以进行独占访问的方法,也就是通过信号量对共享内存实现了同步操作。 如果key当前的key相同,函数将不做任何操作返回。 如果当前的共享内存对象已经链接到底层共享内存段(isAttached),它将在设置新键之前与它分离(detach)。 bool QSharedMemory::attach(QSharedMemory::AccessMode mode = ReadWrite) 该函数将会依据共享内存对象的Key值,来将共享内存对象实际的共享内存逻辑地址相链接

    7130

    php进程(线程)通信基础之System V共享内存简单实例分析

    本文实例讲述了php进程(线程)通信基础之System V共享内存。 ,–enable-sysvshm PHP还挺shmop共享内存,在编译的时候开启 –enable-shmop System V共享内存的相关函数: 1: 创建信号量唯一标识符 $ftok = ftok( __FILE__, 'a'); 2: 创建共享内存端 $id = shm_attach ( $ftok, 1000 , 0666 ) 3: 断开与共享内存段的连接 shm_detach ( $id ) ( $id , $key , $val ) 7: 从共享内存中删除一个变量 shm_remove_var ( $id , $key ) 8: 从系统中删除共享内存 shm_remove ( $id) 更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP进程线程操作技巧总结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《PHP数组(Array)操作技巧大全》、《php字符串(string

    16931

    Java堆内存线程共享的!面试官:你确定吗?

    本文首先带大家了解一下为什么我会说“堆是线程共享内存区域,栈是线程独享的内存区域。”这句话并不完全正确!? 但是,因为堆是全局共享的,因此在同一时间,可能有多个线程在堆上申请空间,那么,在并发场景中,如果两个线程先后把对象引用指向了同一个内存区域,怎么办。 ? 所以说,因为有了TLAB技术,堆内存并不是完完全全的线程共享,其eden区域中还是有一部分空间是分配给线程独享的。 所以,“堆是线程共享内存区域”这句话并不完全正确,因为TLAB是堆内存的一部分,他在读取上确实是线程共享的,但是在内存分配上,是线程独享的。 不管你认不认同作者说的:“堆是线程共享内存区域这句话并不完全正确”。这其实都不重要,重要的是当提到堆内存、提到线程共享、提到对象内存分配的时候,你可以想到还有个TLAB是比较特殊的,就可以了。

    95640

    ThreadLocal子线程共享

    ——雨果 昨天聊了ThreadLocal可以用作单个线程中变量共享 其底层实现其实就是个Map,用线程作为key,不信可以看这部分源码: /** * Returns the value in the (T)e.value; return result; } } return setInitialValue(); } 但是这里有个问题,如果是子线程 中childValue的实现 他直接把传入的值return了出去(绕来绕去的,这里主要是考虑到如果还有别的行为,方便继承后可以拓展) 然后再将子线程作为的key和父value组成一个新的Entry元素 ,把它放到map里去 因此它可以在子线程共享变量,因为它默认的实现就是子线程的key但是存的父值 写个demo测一下: package com.ruben.study; import java.util.concurrent.CompletableFuture InterruptedException { MY_LONG_THREAD.set(0L); MY_LONG_INHERITABLE_THREAD.set(1L); // 单线程共享变量

    6700

    扫码关注腾讯云开发者

    领取腾讯云代金券