用单例模式解决临界区(CRITICAL_SECTION)的使用问题

发表于:2015-12-28 11:19

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:冰雨纷飞    来源:51Testing软件测试网采编

  1.加静态变量标识是否需要InitializeCriticalSection()
  对此这个InitializeCriticalSection(&m_criticalSection);多次的问题,我看到的一种解决方法是,加一个静态变量去标识m_criticalSection所代表的临界区是否已经InitializeCriticalSection(),如果已经InitializeCriticalSection()就不再InitializeCriticalSection()。
  代码如下:
1 class CAVIFile
2 {
3 public:
4     CAVIFile()
5     {
6         if (m_shouldInit)
7         {
8             InitializeCriticalSection(&m_criticalSection); // 初始化临界区
9             m_shouldInit = false;
10         }
11     }
12     HRESULT OpenFile(const string& strFileName, const string& strDirectoryPath)
13     {
14         // ....
15         EnterCriticalSection(&m_criticalSection);
16         SetCurrentDirectory(strDirectoryPath.c_str());
17         // ...
18         LeaveCriticalSection(&m_criticalSection);
19         //...
20     }
21     // ...
22 private:
23     // ...
24     // 整个类设置当前目录的互斥锁
25     static CRITICAL_SECTION m_criticalSection;
26     static bool m_shouldInit;
27 };
28 CRITICAL_SECTION CAVIFile::m_criticalSection;
29 bool  CAVIFile::m_shouldInit = true;
  这其实还是有问题的。在上面的代码中多线程可能同时访问m_shouldInit,判断是否需要InitializeCriticalSection()临界区,如果已经InitializeCriticalSection(),就不再InitializeCriticalSection()初始化临界区,这看起来是正确一样。但是仅仅是看起来。此时,当多线程访问m_shouldInit的时候,m_shouldInit也变成了临界资源了。为了保护m_shouldInit,难道我们再定义一个临界区?那么我们再次定义的临界区的只能InitializeCriticalSection(&m_criticalSection)一次的问题又出现了,我们再定义另一个静态变成去标识我们刚刚为了保护m_shouldInit定义的临界区的只一次InitializeCriticalSection()问题?此时,我们已经落入到蛋生鸡,鸡生蛋的逻辑中了。
  明显这种解决方法是不正确的!
  2、使用单例模式
  在单例模式中,一个使用单例模式的类,只能创建一个类的对象。我突然想起,这个类只能创建一个对象,那么也就是只会调用一次构造函数。那么,我可以利用单例模式进行InitializeCriticalSection()这个临界区。
  实现代码如下:
1 class CAVIFile
2 {
3 public:
4     // ...
5     HRESULT OpenFile(const string& strFileName, const string& strDirectoryPath)
6     {
7         // ....
8         EnterCriticalSection(&m_criticalSection);
9         SetCurrentDirectory(strDirectoryPath.c_str());
10         // ...
11         LeaveCriticalSection(&m_criticalSection);
12         //...
13     }
14     // ...
15 private:
16     //...
17     // 整个类设置当前目录的互斥锁
18     static CRITICAL_SECTION m_criticalSection;
19 private:
20     // Singleton,这个类使用单例模式,为了只初始化一次m_criticalSection
21     // 饿汉式
22     class Singleton
23     {
24     private:
25         Singleton() { InitializeCriticalSection(&m_criticalSection); }
26         Singleton(const Singleton& other);
27         Singleton& operator=(const Singleton& other);
28
29         static Singleton m_Singleton;
30     };
31     friend class Singleton;
32 };
33 CRITICAL_SECTION CAVIFile::m_criticalSection;
34 CAVIFile::Singleton CAVIFile::Singleton::m_Singleton;
  这里,在类内定义了一个嵌套类,而嵌套类使用了饿汉式的单例模式,自动只会构造一次,那么就只会对m_criticalSection ,InitializeCriticalSection()一次。这样就完美的解决了问题。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号