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]#
|