多线程程序操作共享区域(文件)的一点体会

     最近比较忙,很久没有写博客了,持续长时间的编程,使得我完全沦为程序匠人。但是感觉却不是想别人那么糟糕,毕业已经快两年了,我为我的编程兴趣仍然如此强烈而感到欣慰,也对一直以来比较关心的“行业应用软件架构设计”有了更深的了解,这坚定了我的信念!

     今天晚上,终于有了一点点闲暇的时间,就想大家分享下“多线程程序操作共享区域(文件)”的一些体会吧!

 

     多线程相信大家都陌生吧,多线程程序操作共享区域应该也不陌生吧,但是大家是否经历过多CPU的服务器下同时100个线程,操作离散的文件呢?如果每个线程只负责一个固定的文件,那么问题也就不是问题了,但是如果离散的文件,有可能同时被多线程都读写的,那么是否能保证文件读写的数据一致性、是否能保证数据在存储的时候由于非次序存储而导致数据丢失呢?另外,又怎么解决同一段时间同一个线程操作同一个文件的效率问题呢,如果有方法解决,有怎么保证不出现上述第一个问题呢?

    

     摆在面前的二个问题,其实都是编写程序时候,尤其是性能要求比较高的时候,特别需要注意的问题。如下将一一介绍我的一些体会;

 

如何解决多线程多文件操作的数据一致和丢失问题

   解决这个问题,我们要先思考一下,究竟是什么原因导致这个问题呢?答案很明显,主要因为多线程多文件存储时候的时候频繁打开和频繁关闭无次序性导致的,这有点想数据库一样,DBMS是怎么来解决这个问题呢?DBMS有两个方法,一是事务、二是双端锁,其实这两个方法是一个样的道理,在这里我们就不做介绍,有兴趣大家可以查寻些其他的资料。这里我介绍实际应用中我的方法。

   

    我的方法是,保证一个文件在操作的时候,只打开一个实例,打开之后只有一次关闭。

 

    首先来看看,我是如何来设计这样的文件处理单元,我们起名为CDataHandlerUint,大家当作其为结构体就可以了,如下代码;

    typedef struct _DATA_HANDLER_UINT{queue<bool> m_OpenStatusQ; TiXmlDocument m_doc;CString m_strXmlPath;DWORD m_dwOldTicks;}CDataHandlerUint,*PCDataHandlerUint;

    由于我们操作XML文件,因此在这个结构体中,我们保存了一个打开的XML文件实例——m_doc。另外一个重要的成员是m_OpenStatusQ这个暂时命名为XML文件打开请求队列,用于记录文件读写次数。其他成员随后会逐一介绍。

 

    如下来看看,这个结构体在线程内部有是怎么用的,我们还需要一个关键的管理这个结构体的成员,CMap<CString,LPCSTR,PCDataHandlerUint,PCDataHandlerUint> m_mapHandlerUint,m_mapHandlerUint就用来管理这个结构体的。其中m_strXmlPath就是这个MAP的KEY,用来直接搜索出CDataHandlerUint的数据处理单元的pointer。

 

    那么在线程中又怎么来应用这样的一个成员呢?看下如下这个线程的处理过程就明白了;

 

    UINT32 DataHandlerThread(LPVOID pThis){

          (1) 获取要操作的文件路径

          (2) 通过文件路径,获取保存在m_mapHandlerUint的Pointer.

          (3) 如果这个Pointer为NULL,重新NEW,调用m_OpenStatusQ.push(true),之后并添加到MAP中。

         (4)如果这个Pointer不为NULL,调用m_OpenStatusQ.push(true)。

          ............

          (5) 调用m_OpenStatusQ.pop(),之后检测m_OpenStatusQ的size ,如果size为0,保存并关闭XML文件,否则,在根据m_dwOldTicks判断是否超时,如果超时同样保存并关闭XML文件,否则结束函数

    }

 

     这样就应用了MAP加上queue顺利的解决了这个问题,大家看了之后,仔细想想吧!

 

如果线程操作文件时,如果文件存在一定顺序,那么怎么提高效率呢?

     如果一个线程序遇到一个这样的文件系列怎么办,如下文件系列;

      A.xml

      A.xml

      B.xml

      B.xml

      C.xml

      ......

     从这里可以看出,文件是有顺序的,那么如何提高效率呢?

     答案就是,尽量减少文件打开和关闭次数,重复利用已经打开的文件句柄!

 

     这里程序设计的方法其实很简单,只需获取上一次操作文件句柄,并在上次操作的时候不关闭文件,关闭文件的操作放在调用之外,这样当发现两个句柄一样的时候,即调用保存并关闭,当然这里考虑到第一个问题,因此保存并关闭的条件仍然是调用m_OpenStatusQ.pop(),之后检测m_OpenStatusQ的size ,如果size为0,保存并关闭XML文件,否则,在根据m_dwOldTicks判断是否超时,如果超时同样保存并关闭XML文件,否则结束函数。

 

    上述的两个问题,两个方法,只介于本人的体会,肯定还有更好的方法,如大家有兴趣可以联系我本人,方便更深一步的探讨。

 

时间: 2024-10-26 22:58:34

多线程程序操作共享区域(文件)的一点体会的相关文章

局域网共享的文件怎么让别人打开的时候,不影响我删除替换操作

问题描述 局域网共享的文件怎么让别人打开的时候,不影响我删除替换操作,我想做个单位内外网通用的程序,用VS2013c#,但是做成C/S结构的就无法统一更新,所以想放到局域网上,大家都直接打开快捷方式,但在打开的时候,不想影响我更新和替换该程序,做成B/S架构的无法实现内外网通用,服务器在内网谢谢 解决方案 解决方案二:这都在表达什么?"放到局域网,打开快捷方式"就能实现"内外网相通"了?解决方案三:按你的想法,怎么通过外网访问你的共享目录?想要内外网通过,无非是通过

文件传输-下面c语言中要将操作结果存入文件(当遇到#时为止)。程序运行时为什么老是中断出错?

问题描述 下面c语言中要将操作结果存入文件(当遇到#时为止).程序运行时为什么老是中断出错? #include(stdio.h)#include(stdlib.h)void main(){FILE *fp;char ch;if((fp=fopen(""C:UsersAdministratorDesktopEnglish.doc""w""))=NULL){ printf(""cannot open filen"&quo

c++-运行一个C++程序进行文件操作时 打开文件 总会把文件先变为空的 再打开 这是为什么呢?求解

问题描述 运行一个C++程序进行文件操作时 打开文件 总会把文件先变为空的 再打开 这是为什么呢?求解 int main() { system("color 31"); ofstream file("同学录系统.txt",ios::out); if(!file) { system("color 35"); cout<<"对不起,文件打开失败!"< abort(); //程序异常终止进程 } cout int

打开文件夹-在c#智能设备应用程序上,打开文件的操作为什么都是打开网站?

问题描述 在c#智能设备应用程序上,打开文件的操作为什么都是打开网站? 在windows ce5.0 设备上部署后,点击都是进入网页,而不是打开文件夹或文件是为什么? 解决方案 你用 Process.Start() 打开文件,就是用关联程序打开.智能设备上你要打开的文件,它的默认关联程序正好是浏览器吧.

mysql5.7在centos下编写c语言程序操作数据库时,头文件#include&amp;amp;lt;mysql/mysql.h&amp;amp;gt;报错

问题描述 mysql5.7在centos下编写c语言程序操作数据库时,头文件#include<mysql/mysql.h>报错 mysql5.7在centos下编写c语言程序操作数据库时,头文件#include报错 解决方案 这是没有找到plugin_auth_common.h文件啊,你对照一下目录下面有没有这个文件啊...另外这个/usr/include/mysql/mysql目录看起来有点奇怪啊,你是不是多建了一层mysql目录

AT&T似乎要决意打击通过越狱应用程序进行共享操作

美国移动运营商AT&T将打击iPhone以及其他智能电话用户通过手机与其他设备进行未授权共享数据的行为.日前,AT&T向那些用智能电话与附近笔记本电脑共享数据的而又未付费的顾客发出信息:立即停止.目前市场上有很多手机越狱应用程序,包括MyWi在内,可以让用户不需额外付费的情况下共享数据.然而,目前运营商已经找出至少能确定部分未授权共享的办法了,并向他们发出信息表示,要么停止操作要么签署AT&T的相关合同缴费使用.3月18日美国科技博客Boy Genius Report报道了AT&a

在驱动和应用程序间共享内存

在不同的场合,很多驱动编写人员需要在驱动和用户程序间共享内存.两种最容易的技术是:    l 应用程序发送IOCTL给驱动程序,提供一个指向内存的指针,之后驱动程序和应用程序就可以共享内存.(应用程序分配共享内存)    l 由驱动程序分配内存页,并映射这些内存页到指定用户模式进程的地址空间,并且将地址返回给应用程序.(驱动程序分配共享内存)    使用IOCTL共享Buffer:    使用一个IOCT描述的Buffer,在驱动和用户程序间共享内存是内存共享最简单的实现形式.毕竟,IOCTL也

整理总结Java多线程程序编写的要点_java

线程状态图 线程共包括以下5种状态. 1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread(). 2. 就绪状态(Runnable): 也被称为"可执行状态".线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程.例如,thread.start().处于就绪状态的线程,随时可能被CPU调度执行. 3. 运行状态(Running) : 线程获取CPU权限进行执行.需要注意的是,

c# 多线程程序分析,求有经验的前辈们指点

问题描述 环境是windowsserver2008r2+.net2.0运行了一个服务器程序(winform的)该程序是多线程运行的将请求转换成消息分发到不同的消息队列,队列中使用自动复位信号量做同步可是该程序会随机性的出现问题.问题描述:1.表象上感觉像是cpu不够用了,工作线程没有得到cpu时间片,消息队列一直在增长2.界面线程有略卡的现象,本来有一个500ms的定时器,定时刷新界面数据,出现问题时,会出现3-4s的间隔才刷新数据3.不像是线程死循环(因为cpu占用率不高)4.重启程序就恢复了