zoukankan      html  css  js  c++  java
  • c++多线程——锁技巧

    【转自】here

     编写程序不容易,编写多线程的程序更不容易。相信编写过多线程的程序都应该有这样的一个痛苦过程,什么样的情况呢?朋友们应该看一下代码就明白了,

    void data_process()
    {
        EnterCriticalSection();
      
        if(/* error happens */)
        {
            LeaveCriticalSection();
            return;
        }
    
        if(/* other error happens */)
        {
            return;
        }
    
        LeaveCriticalSection();
    }

    上面的代码说明了一种情形。这种多线程的互斥情况在代码编写过程中是经常遇到的。所以,每次对共享数据进行操作时,都需要对数据进行EnterCriticalSection和LeaveCriticalSection的操作。但是,这中间也不是一帆风顺的。很有可能你会遇到各种各样的错误。那么,这时候你的程序就需要跳出去了。可能一开始遇到error的时候,你还记得需要退出临界区。但是,如果错误多了,你未必记得还有这个操作了。这一错就完了,别的线程就没有机会获取这个锁了。
        那么,有没有可能利用C++的特性,自动处理这种情况呢?还真有。我们看看下面这个代码,

    class CLock
    {
        CRITICAL_SECTION& cs;
    
    public:
        CLock(CRITICAL_SECTION& lock):cs(lock){
            EnterCriticalSection(&cs);
        }
    
        ~CLock() {
            LeaveCriticalSection(&cs);
        }
    }
    
    class Process
    {
        CRITICAL_SECTION cs;
        /* other data */
    
    public:
        Process(){
            InitializeCriticalSection(&cs);
        }
    
        ~Process() {DeleteCriticalSection(&cs);}
    
        void data_process(){
            CLock lock(cs);
    
            if(/* error happens */){
                return;
            }
    
            return;
        }
    }

    C++的一个重要特点就是,不管函数什么时候退出,系统都会自动调用类的析构函数。在Process类的data_process函数中,,函数在开始就创建了一个CLock类。那么,在创建这个类的时候,其实就开始了临界区的pk。那么一旦进入到临界区当中,在error中能不能及时退出临界区呢?此时,c++析构函数的优势出现了。因为不管错误什么时候出现,在函数退出之前,系统都会帮我们善后。什么善后呢?就是系统会调用CLock的析构函数,也就是退出临界区。这样,我们的目的就达到了。
        其实,这就是一个c++的trick。

    附上C++的一个线程模板:

    class MutexLock {
    public:
        MutexLock() {
            assert(pthread_mutex_init(&_mutex, NULL) == 0); 
        }   
        ~MutexLock() {
            pthread_mutex_destroy(&_mutex);
        }   
        void lock() {
            assert(pthread_mutex_lock(&_mutex) == 0); 
        }   
        void unlock() {
            assert(pthread_mutex_unlock(&_mutex) == 0); 
        }   
    private:
        pthread_mutex_t _mutex;
    };
    
    class ScopeLocker {
    public:
        ScopeLocker(MutexLock& mutex_lock) {                                                
            _mutex_lock = &mutex_lock;
            _mutex_lock->lock();
        }   
        ~ScopeLocker() {
            _mutex_lock->unlock();
        }   
    private:
        MutexLock* _mutex_lock;
    };

    // 在要加锁的文件中,定义一个全局的 MutexLock , 然后在要加锁的地方,定义 ScopeLocker。如果要限定代码范围用{}把要加锁的代码扩起来。

  • 相关阅读:
    Windows下安装MySQLdb(mysql-python)报错解决
    关于安装bettercap的ERROR: Failed to build gem native extension 报错解决
    Centos6 下启动httpd报错 Could not reliably determine the server's解决方法
    Linux安装mysql-python库时报错解决办法
    [Flask]学习Flask第三天笔记总结
    [原创+实战+钓鱼]setoolkit+映射
    [实战]挖掘CSRF姿势
    [实战]记一次PUT方法拿下网站shell
    JAVA二维数组小记
    技术杂谈
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/7277011.html
Copyright © 2011-2022 走看看