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()一次。这样就完美的解决了问题。