Linux下线程pthread以及锁的一些总结和代码参考

大城市里の小女人 提交于 2020-03-01 04:58:55

    对于linux下线程pthread的认识以及锁的相关概念等等,作为小白的我推荐这一篇比较好的文章,也谢谢大牛的分享:

http://casatwy.com/pthreadde-ge-chong-tong-bu-ji-zhi.html

对于只使用基本mutex的同学,摘录文章中的一段话,共同勉励,一起养成良好的编码规范:

    如果要进入一段临界区需要多个mutex锁,那么就很容易导致死锁,单个mutex锁是不会引发死锁的。要解决这个问题也很简单,只要申请锁的时候 按照固定顺序,或者及时释放不需要的mutex锁就可以。这就对我们的代码有一定的要求,尤其是全局mutex锁的时候,更需要遵守一个约定。

    如果是全局mutex锁,我习惯将它们写在同一个头文件里。一个模块的文件再多,都必须要有两个umbrella header file。一个是整个模块的伞,外界使用你的模块的时候,只要include这个头文件即可。另一个用于给模块的所有子模块去include,然后这个头 文件里面就放一些公用的宏啊,配置啊啥的,全局mutex放在这里就最合适了。这两个文件不能是同一个,否则容易出循环include的问题。如果有人写 模块不喜欢写这样的头文件的,那现在就要改了。

    然后我的mutex锁的命名规则就是:作用_mutex_序号,比LinkListMutex_mutex_1,OperationQueue_mutex_2,后面的序号在每次有新锁的时候,就都加一个1。如果有哪个临界区进入的时候需要获得多个mutex锁的,我就按照序号的顺序去进行加锁操作(pthread_mutex_lock),这样就能够保证不会出现死锁了。

    如果是属于某个struct内部的mutex锁,那么也一样,只不过序号可以不必跟全局锁挂钩,也可以从1开始数。


    以下是本人平时代码中参考别人代码之后,用c++封装的关于锁以及线程同步条件变量的代码参考,欢迎指导:

#ifndef _MUTEX_HELPER_HPP_
#define _MUTEX_HELPER_HPP_

#include <pthread.h>

namespace clientAPI
{
    //互斥锁
    class MutexLock
    {
    public:
        MutexLock(){ pthread_mutex_init(&m_stMutex, NULL); }
        ~MutexLock(){ pthread_mutex_destroy(&m_stMutex); }

        void lock(){ pthread_mutex_lock(&m_stMutex); }
        int unlock() { return pthread_mutex_unlock(&m_stMutex); }

        bool trylock(){ return pthread_mutex_trylock(&m_stMutex) == 0;}
        pthread_mutex_t* getMutexPtr(){ return &m_stMutex;}
    private:
        pthread_mutex_t m_stMutex;
    };

    //读写锁
    class ReadWriteLock
    {
    public:
        ReadWriteLock() { pthread_rwlock_init(&m_stReadWrite, NULL); }
        ~ReadWriteLock() { pthread_rwlock_destroy(&m_stReadWrite); }

        void rdlock() { pthread_rwlock_rdlock(&m_stReadWrite); }
        void wrlock() { pthread_rwlock_wrlock(&m_stReadWrite); }
        void unlock() { pthread_rwlock_unlock(&m_stReadWrite); }

    private:
        pthread_rwlock_t m_stReadWrite;
    };

    //自动互斥锁
    class MutexLockGuard
    {
    public:
        explicit MutexLockGuard(MutexLock& stMutex) : m_rstMutex(stMutex) { m_rstMutex.lock(); }
        ~MutexLockGuard(){ m_rstMutex.unlock(); }

    private:
        MutexLock& m_rstMutex;
    };

    //可选自动互斥锁
    class OptionalMutexLockGuard
    {
    public:
        OptionalMutexLockGuard(MutexLock& stMutex, bool bEnableLock) : 
            m_rstMutex(stMutex),m_bEnableLock(bEnableLock)
        { 
            if(bEnableLock)
                m_rstMutex.lock(); 
        }
        ~OptionalMutexLockGuard()
        {     
            if(m_bEnableLock)
                m_rstMutex.unlock(); 
        }

    private:
        MutexLock& m_rstMutex;
        bool m_bEnableLock;
    };

    //读写锁
    class CRWLock
    {
    public:
        CRWLock() { pthread_rwlock_init(&m_stRWLock, NULL); }
        ~CRWLock() { pthread_rwlock_destroy(&m_stRWLock); }

        int rdlock() { return pthread_rwlock_rdlock(&m_stRWLock); }
        int wrlock() { return pthread_rwlock_wrlock(&m_stRWLock); }
        int unlock() { return pthread_rwlock_unlock(&m_stRWLock); }

    private:
        pthread_rwlock_t m_stRWLock;
    };

    //自动读写锁
    class CRWLockGuard
    {
    public:
        explicit CRWLockGuard(CRWLock &stLock, bool IsReadLock)
            :m_rstLock(stLock)
        {
            if (IsReadLock)
            {
                m_iRet = m_rstLock.rdlock();
            }
            else
            {
                m_iRet = m_rstLock.wrlock();
            }
        }

        int GetLockRetVal(){ return m_iRet; }

        ~CRWLockGuard(){ m_rstLock.unlock(); };
    private:
        CRWLock& m_rstLock;
        int      m_iRet;
    };
    

    class Condition 
    {
    public:
        explicit Condition(MutexLock &mutex) : m_mutex (mutex)
        {
            pthread_cond_init(&m_cond, NULL);
        }

        ~Condition()
        {
            pthread_cond_destroy(&m_cond);
        }

        void wait()
        {
            m_mutex.lock();
            pthread_cond_wait(&m_cond, m_mutex.getMutexPtr() );
            m_mutex.unlock();
        }

        int timewait(const struct timespec& timeout)
        {
            int result = 0;
            m_mutex.lock();
            result = pthread_cond_timedwait(&m_cond, m_mutex.getMutexPtr() , &timeout);
            m_mutex.unlock();
            return result;
        }

        void notify()
        {
            pthread_cond_signal(&m_cond);
        }

        void notifyAll()
        {
            pthread_cond_broadcast(&m_cond);
        }

        // 超时时间设置,单位为毫秒
        void settimeout(struct timespec *tsp , unsigned int timeout_ms)
        {
            struct timeval now;
            gettimeofday(&now, NULL);
            tsp -> tv_sec = now.tv_sec;
            tsp -> tv_nsec = now.tv_usec * 1000 + timeout_ms * 1000 *1000;
            // 设置新的时间点算超时时间
            tsp -> tv_sec += tsp -> tv_nsec/(1000*1000*1000);
            tsp -> tv_nsec = tsp -> tv_nsec%(1000*1000*1000);
        }

    private:
        pthread_cond_t m_cond;
        MutexLock& m_mutex;
    };
}

#endif


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!