zoukankan      html  css  js  c++  java
  • 线程安全

    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----------
    ");
    109     }
    110     ~CTest()
    111     {
    112         printf("----------CTest destruct-----------
    ");
    113     }
    114     void print()
    115     {
    116         printf("CTest call print()
    ");
    117     }
    118 };
    119 
    120 // 可重入函数
    121 void* work(void * arg)
    122 {
    123     CTest* p = CTest::GetInstance();
    124     if (p)
    125     {
    126         printf("CTest pointer = %p
    ", 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
    ", 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
    ", hThread[i]);
    155     }
    156     WaitForMultipleObjects(MAX_COUNT, hThread, TRUE, INFINITE);
    157 #endif
    158 
    159     return 0;
    160 }
  • 相关阅读:
    搜索存储过程中的关键字
    替换回车换行
    js 常用正则表达式
    获取存储过程返回值
    DataReader 转datatable
    文件打包下载
    My97DatePicker设置当天之后的日期不可选变灰色
    嵌套类引用实例化的外部类的方法
    可叠加定义的成员变量的赋值及操作(权限)
    Java中List中remove的实质
  • 原文地址:https://www.cnblogs.com/borey/p/5626072.html
Copyright © 2011-2022 走看看