线程安全
1,原子操作
通常cpu的最小执行单元是一条指令,是不会被打断的。我们把单条指令的操作成为是原子的,但是像自增或自减这样的操作由几条指令组成,是非原子操作。window提供了一些专门的原子操作的API:
2,同步与锁
a,二元信号量(线程间共享)
b,互斥量(mutex)
c,临界区(Critical Section)
d,读写锁(read-write lock)
e,条件变量
3,可重入函数
一个函数被重入有两种情况:
a,多个线程同时执行这个函数
b,函数自身(可能进过多层调用)调用自身
可重入函数是线程并发安全的强力保障,多线程环境下可以放心使用
4,线程安全
没有绝对安全的多线程程序
a,过度优化,编译器对代码执行优化导致非线程安全,如编译器为提高对变量x的访问速度,将其放入寄存器。可以使用volatile修饰
b,CPU动态调度,导致乱序执行
5,线程安全的singleton
/************************************************************************* > File Name: singleton.cpp > Author: xlplbo > Mail: [email protected] > Created Time: Wed 29 Oct 2014 07:01:29 AM PDT ************************************************************************/ #ifdef _WIN32 #include <windows.h> #include <process.h> #define barrier() NULL class CMutex { public: CMutex() { InitializeCriticalSection(&m_CriticalSetion); } ~CMutex() { DeleteCriticalSection(&m_CriticalSetion); } bool Lock() { EnterCriticalSection(&m_CriticalSetion); return true; } bool Unlock() { LeaveCriticalSection(&m_CriticalSetion); return true; } private: CRITICAL_SECTION m_CriticalSetion; }; #else #include <pthread.h> #define barrier() __asm__ __volatile__("":::"memory") class CMutex { public: CMutex() { pthread_mutex_init(&m_Mutex, NULL); } ~CMutex() { pthread_mutex_destroy(&m_Mutex); } bool Lock() { return pthread_mutex_lock(&m_Mutex) == 0; } bool Unlock() { return pthread_mutex_unlock(&m_Mutex) == 0; } private: pthread_mutex_t m_Mutex; }; #endif template <typename T> class singleton { public: static T* GetInstance() { if (!m_pInst) { m_Mutex.Lock(); if (!m_pInst) { T* p = new T; barrier(); //barrier()执行完成之前内存被初始化 m_pInst = p; } m_Mutex.Unlock(); } return m_pInst; } ~singleton() { delete m_pInst; m_pInst = NULL; } private: singleton(); static T* m_pInst; static CMutex m_Mutex; }; template<typename T> T* singleton<T>::m_pInst = NULL; template<typename T> CMutex singleton<T>::m_Mutex; #include <stdio.h> #include <stdlib.h> #ifndef _WIN32 #include <unistd.h> #endif class CTest { public: void print() { printf("CTest call print()\n"); } }; // 可重入函数 void* work(void * arg) { CTest* p = (CTest*)singleton<CTest>::GetInstance(); if (p) { printf("CTest pointer = %p\n", p); p->print(); } #ifndef _WIN32 sleep(5); #else Sleep(5000); #endif return NULL; } int main(int argc, char* argv[]) { const int MAX_COUNT = 10; #ifndef _WIN32 pthread_t p_id[MAX_COUNT]; for (int i = 0; i < MAX_COUNT; i ++) { if (pthread_create(&p_id[i], NULL, work, NULL) != 0) { perror("pthread_create"); exit(0); } printf("create thread id = %d\n", p_id[i]); } for (int i = 0; i < MAX_COUNT; i ++) pthread_join(p_id[i], NULL); #else HANDLE hThread[MAX_COUNT]; for (int i = 0; i < MAX_COUNT; i++) { hThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)work, NULL, 0, NULL); printf("create thread id = %d\n", hThread[i]); } WaitForMultipleObjects(MAX_COUNT, hThread, TRUE, INFINITE); #endif return 1; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。