Fork me on GitHub

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

对于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++封装的关于锁以及线程同步条件变量的代码参考,欢迎指导:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#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
感谢您的赞赏,赚点辛苦奶粉钱