简要分析Java多进程编程的并发控制


进程间的通讯无非就是读写文件,socket通讯或者使用共享内存。
java没法管理内存,其实他也是靠创建映像文件来实现的。
 共享内存在java中的实现
在jdk1.4中提供的类MappedByteBuffer为我们实现共享内存提供了较好的方法。该缓冲区实际上是一个磁盘文件的内存映像。二者的变化将保持同步,即内存数据发生变化会立刻反映到磁盘文件中,这样会有效的保证共享内存的实现。

将共享内存和磁盘文件建立联系的是文件通道类:FileChannel。该类的加入是JDK为了统一对外部设备(文件、网络接口等)的访问方法,并且加强了多线程对同一文件进行存取的安全性。例如读写操作统一成read和write。这里只是用它来建立共享内存用,它建立了共享内存和磁盘文件之间的一个通道。

打开一个文件建立一个文件通道可以用RandomAccessFile类中的方法getChannel。该方法将直接返回一个文件通道。该文件通道由于对应的文件设为随机存取文件,一方面可以进行读写两种操作,另一方面使用它不会破坏映像文件的内容(如果用FileOutputStream直接打开一个映像文件会将该文件的大小置为0,当然数据会全部丢失)。这里,如果用 FileOutputStream和FileInputStream则不能理想的实现共享内存的要求,因为这两个类同时实现自由的读写操作要困难得多。

下面的代码实现了如上功能,它的作用类似UNIX系统中的mmap函数。

// 获得一个只读的随机存取文件对象
RandomAccessFile RAFile = new RandomAccessFile(filename,"r");
// 获得相应的文件通道
FileChannel fc = RAFile.getChannel();
// 取得文件的实际大小,以便映像到共享内存
int size = (int)fc.size();
// 获得共享内存缓冲区,该共享内存只读
MappedByteBuffer mapBuf = fc.map(FileChannel.MAP_RO,0,size);
// 获得一个可读写的随机存取文件对象
RAFile = new RandomAccessFile(filename,"rw");
// 获得相应的文件通道
fc = RAFile.getChannel();
// 取得文件的实际大小,以便映像到共享内存
size = (int)fc.size();
// 获得共享内存缓冲区,该共享内存可读写
mapBuf = fc.map(FileChannel.MAP_RW,0,size);
// 获取头部消息:存取权限
mode = mapBuf.getInt();

如果多个应用映像同一文件名的共享内存,则意味着这多个应用共享了同一内存数据。这些应用对于文件可以具有同等存取权限,一个应用对数据的刷新会更新到多个应用中。
为了防止多个应用同时对共享内存进行写操作,可以在该共享内存的头部信息加入写操作标志。该共享内存的头部基本信息至少有:

int Length; // 共享内存的长度。
int mode; // 该共享内存目前的存取模式。

 
共享内存的头部信息是类的私有信息,在多个应用可以对同一共享内存执行写操作时,开始执行写操作和结束写操作时,需调用如下方法:

public boolean StartWrite()
{
  if(mode == 0) { // 标志为0,则表示可写
   mode = 1; // 置标志为1,意味着别的应用不可写该共享内存
   mapBuf.flip(); 
   mapBuf.putInt(mode); // 写如共享内存的头部信息
   return true;
 }
 else {
  return false; // 指明已经有应用在写该共享内存,本应用不可写该共享内存
 }
}
public boolean StopWrite()
{
 mode = 0; // 释放写权限
 mapBuf.flip(); 
 mapBuf.putInt(mode); // 写入共享内存头部信息
 return true;
}

这里提供的类文件mmap.java封装了共享内存的基本接口,读者可以用该类扩展成自己需要的功能全面的类。
 
如果执行写操作的应用异常中止,那么映像文件的共享内存将不再能执行写操作。为了在应用异常中止后,写操作禁止标志自动消除,必须让运行的应用获知退出的应用。在多线程应用中,可以用同步方法获得这样的效果,但是在多进程中,同步是不起作用的。方法可以采用的多种技巧,这里只是描述一可能的实现:采用文件锁的方式。写共享内存应用在获得对一个共享内存写权限的时候,除了判断头部信息的写权限标志外,还要判断一个临时的锁文件是否可以得到,如果可以得到,则即使头部信息的写权限标志为1(上述),也可以启动写权限,其实这已经表明写权限获得的应用已经异常退出,这段代码如下:

// 打开一个临时的文件,注意同一共享内存,该文件名要相同,可以在共享文件名后加后缀“.lock”。
RandomAccessFile fis = new RandomAccessFile("shm.lock","rw");
// 获得文件通道
FileChannel lockfc = fis.getChannel();
// 获得文件的独占锁,该方法不产生堵塞,立刻返回
FileLock flock = lockfc.tryLock();
// 如果为空,则表明已经有应用占有该锁
if(flock == null) {
...// 不能执行写操作
}else {
...// 可以执行写操作
}

该锁会在应用异常退出后自动释放,这正是该处所需要的方法。



相关阅读:
论JavaScript模块化编程
深入浅析JS的数组遍历方法(推荐)
ThinkPHP视图查询详解
HTML5 canvas基本绘图之绘制线段
VC基于ADO技术访问数据库的方法
Android编程之内存溢出解决方案(OOM)实例总结
Android图片处理实例介绍(图)
android预置默认的语音信箱号码具体实现
Java编程中字节流与字符流IO操作示例
VC创建DLL动态链接库的方法
jQuery插件制作之参数用法实例分析
JS文字球状放大效果代码分享
Ubuntu15.04桌面操作系统怎么安装?
使用ajax操作 JavaScript 对象
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 描写心情的句子 祖国在我心中作文600字 区安监局2016年精神文明创建工作总结 《纳兰容若词传》读后感 永远的布谷鸟读后感300字 关于初夏的诗句 大学生团员的入党申请书 小鸡观察日记600字 你已经在正确的道路上 人民广场在哭泣400字 聪明机灵的猴大臣 岁月如歌 人生如潮 写景篇四年级优秀作文 家访手记:孩子就是全世界 小学英语学科周活动代表发言稿 2014年的小学清明节作文 丢不掉 2016年中心卫生院院长述职述廉报告 梦一场梦,一个故事在跳动 分裂 高中高一作文1000字:跟时代一起改变IV 如果我住在江南 “三下乡”先进事迹 试谈《南州六月荔枝丹》的教学设计 经典爱情短信:恋人情人爱情絮语 永远坐在前排读后感 党员干部廉洁从政心得体会 副局长自查剖析 信访局上半年信访工作总结 随行的思念 学习推进三项重点工作讲话精神 我爱唠叨的妈妈读后感100字 掌握小学生作文开头的方法和技巧 《我眼中的泉州》 【原创】可惜,不是你陪我到最后 夜寂静 初中初三作文450字:幸福的定义 外婆的关心作文600字 初中初三作文350字:《夏天随笔》——暑期快乐写作(3) 医院住院医生规章制度 品悟人生 咫尺天涯,擦肩而过作文150字 缓慢的力量 繁华凋落,我们是否会伤 初中初二作文500字:读《谁动了我的奶酪》有感 安妮宝贝莲花读后感 中学校园文化建设的策划书 荒城(小说) 在你的微笑里我才有了呼吸 让人心疼的伤感句子 一次特殊的采访_关于采访的小学生记事作文550字

Copyright © 2016 phpStudy |