对UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种,对windows实际上只有映像文件共享内存一种。所以java应用中也是只能创建映像文件共享内存。使用共享内存,有如下几个特点:
1、可以被多个进程打开访问。
2、读写操作的进程在执行读写操作时其他进程不能进行写操作。
3、多个进程可以交替对某一共享内存执行写操作。
4、一个进程执行了内存的写操作后,不影响其他进程对该内存的访问。同时其他进程对更新后的内存具有可见性。
5、在进程执行写操作时,如果异常退出,对其他进程写操作禁止应自动解除。
一般我们操作共享内存有以下几种情况,主要关注1,2:
1、独占的写操作,相应有独占的写操作等待队列。独占的写操作本身不会发生数据的一致性问题。
2、共享的写操作,相应有共享的写操作等待队列。共享的写操作哦则要注意防止发生数据的一致性问题。
3、独占的读操作,相应有共享的读操作等待队列。
4、共享的读操作,相应有共享的读操作等待队列。
在jdk1.4中提供的类MappedByteBuffer为我们提供了实现共享内存的方法,该缓冲区实际上是一个磁盘文件的内存映像。二者的变化保持同步,即内存数据发生变化会立刻反应到磁盘文件中,这样会有效的保证共享内存的实现。废话不多说,直接看代码:
package com.hx.sharemem; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.Properties; import com.hx.util.FileUtil; /** * 共享内存操作类 * @author hx * */ public class ShareMemory { int flen = 41779264; //开辟共享内存大小 int fsize = 0; //文件的实际大小 String shareFileName; //共享内存文件名 String sharePath; //共享内存路径 MappedByteBuffer mapBuf = null; //定义共享内存缓冲区 FileChannel fc = null; //定义相应的文件通道 FileLock fl = null; //定义文件区域锁定的标记。 Properties p = null; RandomAccessFile RAFile = null; //定义一个随机存取文件对象 /** * * @param sp 共享内存文件路径 * @param sf 共享内存文件名 */ public ShareMemory(String sp, String sf) { if (sp.length() != 0) { FileUtil.CreateDir(sp); this.sharePath = sp + File.separator; } else { this.sharePath = sp; } this.shareFileName = sf; try { // 获得一个只读的随机存取文件对象 "rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 RAFile = new RandomAccessFile(this.sharePath + this.shareFileName + ".sm", "rw"); //获取相应的文件通道 fc = RAFile.getChannel(); //获取实际文件的大小 fsize = (int) fc.size(); if (fsize < flen) { byte bb[] = new byte[flen - fsize]; //创建字节缓冲区 ByteBuffer bf = ByteBuffer.wrap(bb); bf.clear(); //设置此通道的文件位置。 fc.position(fsize); //将字节序列从给定的缓冲区写入此通道。 fc.write(bf); fc.force(false); fsize = flen; } //将此通道的文件区域直接映射到内存中。 mapBuf = fc.map(FileChannel.MapMode.READ_WRITE, 0, fsize); } catch (IOException e) { e.printStackTrace(); } } /** * * @param ps 锁定区域开始的位置;必须为非负数 * @param len 锁定区域的大小;必须为非负数 * @param buff 写入的数据 * @return */ public synchronized int write(int ps, int len, byte[] buff) { if (ps >= fsize || ps + len >= fsize) { return 0; } //定义文件区域锁定的标记。 FileLock fl = null; try { //获取此通道的文件给定区域上的锁定。 fl = fc.lock(ps, len, false); if (fl != null) { mapBuf.position(ps); ByteBuffer bf1 = ByteBuffer.wrap(buff); mapBuf.put(bf1); //释放此锁定。 fl.release(); return len; } } catch (Exception e) { if (fl != null) { try { fl.release(); } catch (IOException e1) { System.out.println(e1.toString()); } } return 0; } return 0; } /** * * @param ps 锁定区域开始的位置;必须为非负数 * @param len 锁定区域的大小;必须为非负数 * @param buff 要取的数据 * @return */ public synchronized int read(int ps, int len, byte[] buff) { if (ps >= fsize) { return 0; } //定义文件区域锁定的标记。 FileLock fl = null; try { fl = fc.lock(ps, len, false); if (fl != null) { //System.out.println( "ps="+ps ); mapBuf.position(ps); if (mapBuf.remaining() < len) { len = mapBuf.remaining(); } if (len > 0) { mapBuf.get(buff, 0, len); } fl.release(); return len; } } catch (Exception e) { if (fl != null) { try { fl.release(); } catch (IOException e1) { System.out.println(e1.toString()); } } return 0; } return 0; } /** * 完成,关闭相关操作 */ protected void finalize() throws Throwable { if (fc != null) { try { fc.close(); } catch (IOException e) { System.out.println(e.toString()); } fc = null; } if (RAFile != null) { try { RAFile.close(); } catch (IOException e) { System.out.println(e.toString()); } RAFile = null; } mapBuf = null; } /** * 关闭共享内存操作 */ public synchronized void closeSMFile() { if (fc != null) { try { fc.close(); } catch (IOException e) { System.out.println(e.toString()); } fc = null; } if (RAFile != null) { try { RAFile.close(); } catch (IOException e) { System.out.println(e.toString()); } RAFile = null; } mapBuf = null; } /** * 检查退出 * @return true-成功,false-失败 */ public synchronized boolean checkToExit() { byte bb[] = new byte[1]; if (read(1, 1, bb) > 0) { if (bb[0] == 1) { return true; } } return false; } /** * 复位退出 */ public synchronized void resetExit() { byte bb[] = new byte[1]; bb[0] = 0; write(1, 1, bb); } /** * 退出 */ public synchronized void toExit() { byte bb[] = new byte[1]; bb[0] = 1; write(1, 1, bb); } public static void main(String arsg[]) throws Exception{ ShareMemory sm = new ShareMemory("E://demo","test"); String str = "中文测试"; sm.write(40, 20, str.getBytes("UTF-8")); byte[] b = new byte[20]; sm.read(40, 20, b); System.out.println(new String(b,"UTF-8")); } }
相关推荐
Java 实现内存动态分配主要涉及Java内存模型以及内存管理...综上所述,Java实现内存动态分配涉及到对堆内存、栈内存的理解,以及对垃圾回收机制的掌握。通过实验模拟,可以更直观地了解这些概念在实际操作中的应用。
本文将深入探讨如何在Android中利用C++实现共享内存,并结合Binder机制进行跨进程通信。 首先,我们需要了解C++在Android中的应用。Android NDK(Native Development Kit)提供了一个平台,开发者可以在Android应用...
Java虽然原生并不直接支持共享内存,但可以通过NIO(New IO)库中的MAPPED_BUFFER类,结合底层操作系统提供的文件映射功能来间接实现。文件映射编程是将一个文件或者一部分文件映射到进程的虚拟地址空间,这样就可以...
在这个“共享内存实现代码shmem”的示例中,我们将深入探讨如何在编程中创建、写入和读取共享内存。 首先,我们要知道在Unix-like系统(如Linux)中,共享内存主要通过`sys/shm.h`头文件中的函数来操作,比如`...
- `TestSMDlg.cpp`和`TestSM.cpp`可能包含了主程序的逻辑,其中`TestSMDlg`可能涉及用户界面对话框的处理,而`TestSM`则负责共享内存的操作。 - `StdAfx.cpp`和`StdAfx.h`通常是Visual C++项目中的预编译头文件,...
在Java中,可以通过`java.nio.MappedByteBuffer`类来实现共享内存功能,这被称为内存映射文件(Memory-Mapped File,MMF)。 `MappedByteBuffer`是NIO中的一种特殊缓冲区,它将文件的一部分映射到内存中,使得文件...
操作系统课程设计-Spooling技术Java实现 在计算机科学领域,SPOOLing(Simultaneous Peripheral Operations On Line)技术是一种改善I/O(输入/输出)效率的机制,它使得多个进程可以共享有限的独占型外围设备,如...
3. **共享内存**:通过共享内存区域进行进程间的快速通信。 4. **套接字通信**:在不同进程甚至不同机器之间使用网络套接字进行通信。 在这个项目中,"ChineseOS 1.1"可能是源代码和设计文档的文件名,它提供了实现...
“因果性”确保了内存操作和线程行为之间建立了一种因果关联。 Java内存模型的正式规范还包括了对行为和执行的定义,以及对良好形成执行、非终止执行和执行与因果性要求的详细描述。规范中详细讨论了不同线程间可能...
1. 共享内存:它是一种操作系统提供的机制,允许多个进程访问同一块内存空间,从而实现数据共享。在Unix和类Unix系统(如Linux)中,可以使用`mmap()`函数或`shmget()`/`shmat()`等系统调用来创建和操作共享内存。 2...
Java编程语言将内存划分为两种主要区域:栈内存(Stack Memory)和堆内存(Heap Memory),这两种内存区域各自承担不同的职责,对程序的运行起到关键作用。 栈内存主要用于存储基本类型变量(如int、char)和对象的...
### 操作系统概念-java实现第7版答案解析 #### 知识点一:多程序环境下的安全问题 在多程序并行执行与时间共享环境中,多个用户会同时使用系统资源,这种情况下可能会出现多种安全问题。 1. **两种具体的安全问题...
Java采用的是共享内存模型,线程间通过共享变量来隐式通信。 Java内存模型定义了线程和主内存之间的抽象关系,即所有共享变量存储在主内存中,每个线程都有自己的本地内存,用于存储共享变量的副本。本地内存并不是...
在这个“操作系统作业”中,我们将探讨五个关键的实现部分,它们包括PV操作、作业管理以及另外三个未明确提及的组件,可能是进程调度、内存管理和I/O操作。这些内容通常涵盖在操作系统原理课程中,并且用Java语言来...
在C++实现的共享内存与Java的交互过程中,可以通过JNI接口在Java层创建对C++函数的调用,从而实现跨语言的共享内存操作。 对于C#,Windows提供了.NET Framework,其中的`System.Threading命名空间`提供了`Memory...
在现代计算机系统中,由于物理内存有限,当多个进程共享内存时,就会出现内存不足的情况。为了解决这个问题,操作系统会采用一种称为页面替换的技术,将暂时不使用的内存页面换出到磁盘上的交换空间,从而腾出内存给...
Java内存模型,简称JMM(Java Memory Model),是Java编程语言规范的一部分,它定义了程序中各个线程如何访问和修改共享变量,以及如何确保数据的一致性。深入理解Java内存模型对于编写高效的并发程序至关重要。本文...
**操作系统和虚拟内存**:现代操作系统通过虚拟内存技术实现了多个进程间的内存共享,每个进程拥有自己独立的虚拟地址空间。操作系统会根据需要在物理内存与交换空间之间动态迁移数据,以优化物理内存的使用效率。 ...
Java内存模型使用共享内存模型,这意味着线程之间的通信是通过共享内存来完成的。具体来说,JMM定义了线程和主内存之间的抽象关系,共享变量存储在主内存中,而每个线程都有自己的私有本地内存,其中包含该线程读写...
在Java内存模型中,原子操作是不可分割的操作,比如对一个整型变量的增加或者减少操作。虽然在硬件层面上,这些操作可能不是原子的,但是JVM会在执行这些操作时加入必要的同步措施,以保证在多线程环境中的原子性。 ...