IPC组件的分装之互斥锁(14)

本文介绍了一个基于pthread的MutexLock及MutexLockGuard类的实现。MutexLock用于线程同步,通过记录持有者PID确保互斥访问;MutexLockGuard作为RAII风格的锁守卫,简化了加解锁操作。

MutexLock 的封装

    MutexLock类图

--------------------------------------------

-mutex_:pthread_mutex_t

-holder_:pid_t //线程的真实ID,用来表示拥有锁的线程

-----------------------------

<<create>>-MutexLock()

<<destroy>>-MutexLock

+isLockedByThisThread:bool // 当前线程是否拥有该锁

+assertLocked():void //断言当前线程是否拥有该锁

+lock():void

+unlock():void

+getPthreadMutex():pthread_mutex_t *

--------------------------------------------


    MutexLockGuard类图封装

-------------------------

-mutex_:MutexLock &

-----------

<<create>>-MutexLockGurad(mutex:MutexLock&)

<<destroy>>-MutexLockGurad()



MutexLockGuard

    MutexLockGuard 类图


-------------------

-mutex_:MutexLock&

<<create>>-MutexLockGuard(mutex:MutexLock&)

<<destroy>>-MutexLockGuard()

--------------------





MutexLock 和 MutexLockGuard的源代码

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
/ Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
 
#ifndef MUDUO_BASE_MUTEX_H
#define MUDUO_BASE_MUTEX_H
 
#include <muduo/base/CurrentThread.h>
#include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h>
 
namespace muduo
{
 
class MutexLock : boost::noncopyable //表示该类不能复制
{
 public:
  MutexLock()
    : holder_(0)
  {
     //初始化锁
    int ret = pthread_mutex_init(&mutex_, NULL);
    assert(ret == 0); (void) ret;
  }
 
  ~MutexLock()
  {
      //断言该锁是否还在使用
    assert(holder_ == 0);
    //没用呗使用则销毁锁资源
    int ret = pthread_mutex_destroy(&mutex_);
    assert(ret == 0); (void) ret;
  }
 //测试当前线程是否拥有锁
  bool isLockedByThisThread()
  {
    return holder_ == CurrentThread::tid();
  }
//断言锁
  void assertLocked()
  {
    assert(isLockedByThisThread());
  }
 
  // internal usage
//当前线程枷锁
  void lock()
  {
    pthread_mutex_lock(&mutex_);
    holder_ = CurrentThread::tid();
  }
//当前线程解锁
  void unlock()
  {
    holder_ = 0;
    pthread_mutex_unlock(&mutex_);
  }
 
  pthread_mutex_t* getPthreadMutex() /* non-const */
  {
    return &mutex_;
  }
 
 private:
 
  pthread_mutex_t mutex_;
  pid_t holder_;
};
 
 
class MutexLockGuard : boost::noncopyable //不可复制
{
 public:
//构造时负责枷锁
  explicit MutexLockGuard(MutexLock& mutex)
    : mutex_(mutex)
  {
    mutex_.lock();
  }
//虚构时负责解锁,但是并没有销毁mutex_
  ~MutexLockGuard()
  {
    mutex_.unlock();
  }
 
 private:
// MutexLock &mutex 的生存期并不会被MutexLockGuard管理
 //他们的关系是关联的。
 // 聚合关系:表示A包含B
 // 组合关系:表示A包含B,并且负责B的生存期
  MutexLock& mutex_;
};
 
}
 
// Prevent misuse like:
// MutexLockGuard(mutex_); 防止匿名对象
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"
 
#endif  // MUDUO_BA



测试代码

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
#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/Timestamp.h>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>
#include <stdio.h>
 
using namespace muduo;
using namespace std;
 
MutexLock g_mutex;
vector<int> g_vec;
const int kCount = 10*1000*1000;
 
void threadFunc()
{
    //插入kCount个整数
  for (int i = 0; i < kCount; ++i)
  {
      //没循环一次加解锁一次,这里花费的时间会多点
    MutexLockGuard lock(g_mutex);
    g_vec.push_back(i);
  }
}
 
int main()
{
    //最多8 个线程
  const int kMaxThreads = 8;、
    //预留8千多万个整数 , 300多m
  g_vec.reserve(kMaxThreads * kCount);
    //登记一个时间戳
  Timestamp start(Timestamp::now());
    //插入kCount多个整数
  for (int i = 0; i < kCount; ++i)
  {
    g_vec.push_back(i);
  }
    //单线程 统计插入kCount个整数所用时间
  printf("single thread without lock %f\n", timeDifference(Timestamp::now(), start));
 
  start = Timestamp::now();
  threadFunc();
  printf("single thread with lock %f\n", timeDifference(Timestamp::now(), start));
 
  for (int nthreads = 1; nthreads < kMaxThreads; ++nthreads)
  {
    //这是一个指针vector,存放的是Thread乐行的指针
    //智能指针,释放threads时,它里面的对象也会被销毁
    boost::ptr_vector<Thread> threads;
    g_vec.clear();
    start = Timestamp::now();
    /*
    第一次 1 个线程, 第二次2个线程.....,不同线程个数时所花费的时间
    **/
    for (int i = 0; i < nthreads; ++i)
    {
      threads.push_back(new Thread(&threadFunc));
      //启动最后一个对象的线程,其实就是每增加一个,然后就执行它
      threads.back().start();
    }
    //等待线程的结束
    for (int i = 0; i < nthreads; ++i)
    {
      threads[i].join();
    }
    //计算时间差
    printf("%d thread(s) with lock %f\n", nthreads, timeDifference(Timestamp::now(), start));
  }
}

程序输出

1
2
3
4
5
6
7
8
9
10
11
[root@localhost bin]# ./mutex_test
single thread without lock 1.512640
single thread with lock 1.305807
1 thread(s) with lock 0.685571
2 thread(s) with lock 3.381297
3 thread(s) with lock 4.640776
4 thread(s) with lock 5.383397
5 thread(s) with lock 7.897223
6 thread(s) with lock 21.798079
7 thread(s) with lock 23.351875
[root@localhost bin]#


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值