线程安全

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

  1 #ifdef _WIN32
  2 #include <windows.h>
  3 #include <process.h>
  4 #define barrier() NULL
  5 class CMutex
  6 {
  7 public:
  8     CMutex()
  9     {
 10         InitializeCriticalSection(&m_CriticalSetion);
 11     }
 12     ~CMutex()
 13     {
 14         DeleteCriticalSection(&m_CriticalSetion);
 15     }
 16     bool Lock()
 17     {
 18         EnterCriticalSection(&m_CriticalSetion);
 19         return true;
 20     }
 21     bool Unlock()
 22     {
 23         LeaveCriticalSection(&m_CriticalSetion);
 24         return true;
 25     }
 26 private:
 27     CRITICAL_SECTION m_CriticalSetion;
 28 };
 29 #else
 30 #include <pthread.h>
 31 #define barrier() __asm__ __volatile__("":::"memory")
 32 class CMutex
 33 {
 34 public:
 35     CMutex()
 36     {
 37         pthread_mutex_init(&m_Mutex, NULL);
 38     }
 39     ~CMutex()
 40     {
 41         pthread_mutex_destroy(&m_Mutex);
 42     }
 43     bool Lock()
 44     {
 45         return pthread_mutex_lock(&m_Mutex) == 0;
 46     }
 47     bool Unlock()
 48     {
 49         return pthread_mutex_unlock(&m_Mutex) == 0;
 50     }
 51 private:
 52     pthread_mutex_t m_Mutex;
 53 };
 54 #endif
 55 
 56 template <typename T>
 57 class singleton
 58 {
 59 public:
 60     static T* GetInstance()
 61     {
 62         if (!m_pInst)
 63         {
 64             m_Mutex.Lock();
 65             if (!m_pInst)
 66             {
 67                 T* p = new T;
 68                 barrier(); //barrier()执行完成之前内存被初始化
 69                 m_pInst = p;
 70             }
 71             m_Mutex.Unlock();
 72         }
 73         return m_pInst;
 74     }
 75 protected:
 76     singleton(){}
 77     virtual ~singleton(){}
 78     static T* m_pInst;
 79     static CMutex m_Mutex;
 80 
 81 private:
 82     class C1234567
 83     {
 84         ~C1234567()
 85         {
 86             delete m_pInst;
 87             m_pInst = NULL;
 88         }
 89     };
 90     static C1234567 m_C1234567;
 91 };
 92 
 93 template<typename T> T* singleton<T>::m_pInst = NULL;
 94 template<typename T> CMutex singleton<T>::m_Mutex;
 95 template<typename T> typename singleton<T>::C1234567 singleton<T>::m_C1234567;
 96 
 97 #include <stdio.h>
 98 #include <stdlib.h>
 99 #ifndef _WIN32
100 #include <unistd.h>
101 #endif
102 
103 class CTest : public singleton<CTest>
104 {
105 public:
106     CTest()
107     {
108         printf("----------CTest construct----------\n");
109     }
110     ~CTest()
111     {
112         printf("----------CTest destruct-----------\n");
113     }
114     void print()
115     {
116         printf("CTest call print()\n");
117     }
118 };
119 
120 // 可重入函数
121 void* work(void * arg)
122 {
123     CTest* p = CTest::GetInstance();
124     if (p)
125     {
126         printf("CTest pointer = %p\n", p);
127         p->print();
128     }
129 
130     return NULL;
131 }
132 
133 int main(int argc, char* argv[])
134 {
135     const int MAX_COUNT = 10;
136 #ifndef _WIN32
137     pthread_t p_id[MAX_COUNT];
138     for (int i = 0; i < MAX_COUNT; i ++)
139     {
140         if (pthread_create(&p_id[i], NULL, work, NULL) != 0)
141         {
142             perror("pthread_create");
143             exit(0);
144         }
145         printf("create thread id = %d\n", p_id[i]);
146     }
147     for (int i = 0; i < MAX_COUNT; i ++)
148         pthread_join(p_id[i], NULL);
149 #else
150     HANDLE hThread[MAX_COUNT];
151     for (int i = 0; i < MAX_COUNT; i++)
152     {
153         hThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)work, NULL, 0, NULL);
154         printf("create thread id = %d\n", hThread[i]);
155     }
156     WaitForMultipleObjects(MAX_COUNT, hThread, TRUE, INFINITE);
157 #endif
158 
159     return 0;
160 }

 

posted @ 2016-06-29 10:54  borey  阅读(281)  评论(0编辑  收藏  举报