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

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

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

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

 

     多线程相信大家都陌生吧,多线程程序操作共享区域应该也不陌生吧,但是大家是否经历过多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文件,否则结束函数。

 

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

 

目录
相关文章
|
3月前
|
Java 开发者
如何通过易语言多线程提升程序响应速度
如何通过易语言多线程提升程序响应速度
224 62
|
2月前
|
安全 Java
线程安全的艺术:确保并发程序的正确性
在多线程环境中,确保线程安全是编程中的一个核心挑战。线程安全问题可能导致数据不一致、程序崩溃甚至安全漏洞。本文将分享如何确保线程安全,探讨不同的技术策略和最佳实践。
46 6
|
3月前
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
Lua的面向对象编程、协同线程与协同函数的概念和使用,以及Lua文件I/O操作的基本方法。
40 4
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
|
3月前
|
Java 开发者
如何通过易语言多线程提升程序响应速度?
如何通过易语言多线程提升程序响应速度?
|
7月前
|
分布式计算 并行计算 安全
在Python Web开发中,Python的全局解释器锁(Global Interpreter Lock,简称GIL)是一个核心概念,它直接影响了Python程序在多线程环境下的执行效率和性能表现
【6月更文挑战第30天】Python的GIL是CPython中的全局锁,限制了多线程并行执行,尤其是在多核CPU上。GIL确保同一时间仅有一个线程执行Python字节码,导致CPU密集型任务时多线程无法充分利用多核,反而可能因上下文切换降低性能。然而,I/O密集型任务仍能受益于线程交替执行。为利用多核,开发者常选择多进程、异步IO或使用不受GIL限制的Python实现。在Web开发中,理解GIL对于优化并发性能至关重要。
74 0
|
3月前
|
监控 Java API
|
4月前
|
安全 算法 Java
多线程写入同一个文件时,如何保证写入正常
【9月更文挑战第3天】多线程写入同一个文件时,如何保证写入正常
659 8
|
5月前
|
Rust 并行计算 安全
揭秘Rust并发奇技!线程与消息传递背后的秘密,让程序性能飙升的终极奥义!
【8月更文挑战第31天】Rust 以其安全性和高性能著称,其并发模型在现代软件开发中至关重要。通过 `std::thread` 模块,Rust 支持高效的线程管理和数据共享,同时确保内存和线程安全。本文探讨 Rust 的线程与消息传递机制,并通过示例代码展示其应用。例如,使用 `Mutex` 实现线程同步,通过通道(channel)实现线程间安全通信。Rust 的并发模型结合了线程和消息传递的优势,确保了高效且安全的并行执行,适用于高性能和高并发场景。
83 0
|
5月前
|
开发框架 Android开发 iOS开发
跨平台开发的双重奏:Xamarin在不同规模项目中的实战表现与成功故事解析
【8月更文挑战第31天】在移动应用开发领域,选择合适的开发框架至关重要。Xamarin作为一款基于.NET的跨平台解决方案,凭借其独特的代码共享和快速迭代能力,赢得了广泛青睐。本文通过两个案例对比展示Xamarin的优势:一是初创公司利用Xamarin.Forms快速开发出适用于Android和iOS的应用;二是大型企业借助Xamarin实现高性能的原生应用体验及稳定的后端支持。无论是资源有限的小型企业还是需求复杂的大公司,Xamarin均能提供高效灵活的解决方案,彰显其在跨平台开发领域的强大实力。
59 0