首页 > CLucene, 程序人生 > CLucene源码剖析(三) 实现跨平台的线程安全
CLucene源码剖析(三) 实现跨平台的线程安全
2009年5月29日 小武哥 发表评论 阅读评论
在多线程编程中,程序的线程安全(thread-safe)是十分重要的,要做到这一点,一方面要在程序设计的过程中,尽可能设计多的单线程访问的数据结构,一方面就是合理的使用锁(Mutex)。在CLucene中,实现了如下跨平台的锁相关的宏:
(1) _LUCENE_SLEEP(x) 挂起当前线程 x微秒
(2) _LUCENE_THREADMUTEX 线程锁(mutex)
(3) _LUCENE_CURRTHREADID 获取当前线程的thread ID
(4) _LUCENE_THREADID_TYPE thread ID的类型定义
通过上面几个宏,就可以实现基本的线程安全的相关操作。下面对上述宏的具体实现进行一一详细说明:
1.在windows平台下:
(1) _LUCENE_SLEEP(x)由系统API Sleep()实现
1
#define _LUCENE_SLEEP(x) Sleep(x)
(2) _LUCENE_THREADMUTEX由CRITICAL_SECTION相关的内容实现
1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_win32
(3) _LUCENE_CURRTHREADID由系统API GetCurrentThreadId()实现
1
#define _LUCEN colla="E_CURRTHREADID GetCurrentThreadId()
(4) _LUCENE_THREADID_TYPE类型为 DWORD类型
1
#define _LUCENE_THREADID_TYPE DWORD
2.在unix平台下:
(1) _LUCENE_SLEEP(x)由系统函数 usleep()实现
1
#define _LUCENE_SLEEP(x) usleep(x*1000)
(2) _LUCENE_THREADMUTEX由pthread_mutex_t相关的内容实现
1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_pthread
(3) _LUCENE_CURRTHREADID由pthread中的pthread_self()的实现
1
#define _LUCENE_CURRTHREADID pthread_self()
(4) _LUCENE_THREADID_TYPE类型为pthread_t类型
1
#define _LUCENE_THREADID_TYPE pthread_t
从上面的讲解过程中,我们可以看出_LUCENE_THREADMUTEX的实现,还是有一层包装的,在windows下是mutex_win32,在unix下是mutex_pthread,所以要想深入理解,还需要更加深入一步。
下面是mutex_win32的实现:
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
class mutex_win32
{
private:
CRITICAL_SECTION mtx;
public:
mutex_win32(const mutex_win32& clone);
mutex_win32();
~mutex_win32();
void lock();
void unlock();
};
mutex_win32::mutex_win32(const mutex_win32& clone){
InitializeCriticalSection(&mtx);
}
mutex_win32::mutex_win32()
{
InitializeCriticalSection(&mtx);
}
mutex_win32::~mutex_win32()
{
DeleteCriticalSection(&mtx);
}
void mutex_win32::lock()
{
EnterCriticalSection(&mtx);
}
void mutex_win32::unlock()
{
LeaveCriticalSection(&mtx);
}
下面是mutex_pthread的实现:
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
class mutex_pthread
{
private:
pthread_mutex_t mtx;
public:
mutex_pthread(const mutex_pthread& clone);
mutex_pthread();
~mutex_pthread();
void lock();
void unlock();
private:
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t lockOwner;
unsigned int lockCount;
#endif
};
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
bool mutex_pthread_attr_initd=false;
pthread_mutexattr_t mutex_pthread_attr;
#endif
#ifdef _CL__CND_DEBUG
#define _CLPTHREAD_CHECK(c,m) CND_PRECONDITION(c==0,m)
#else
#define _CLPTHREAD_CHECK(c,m) c;
#endif
mutex_pthread::mutex_pthread(const mutex_pthread& clone){
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}
mutex_pthread::mutex_pthread()
{
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
if ( mutex_pthread_attr_initd == false ){
pthread_mutexattr_init(&mutex_pthread_attr);
pthread_mutexattr_settype(&mutex_pthread_attr, PTHREAD_MUTEX_RECURSIVE);
mutex_pthread_attr_initd = true;
}
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}
mutex_pthread::~mutex_pthread()
{
_CLPTHREAD_CHECK(pthread_mutex_destroy(&mtx), "~mutex_pthread destructor failed")
}
void mutex_pthread::lock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t currentThread = pthread_self();
if( pthread_equal( lockOwner, currentThread ) ) {
++lockCount;
} else {
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
lockOwner = currentThread;
lockCount = 1;
}
#else
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
#endif
}
void mutex_pthread::unlock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
--lockCount;
if( lockCount == 0 )
{
lockOwner = 0;
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
}
#else
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
#endif
}
由上面的实现可以看出,mutex_win32直接就是对CRITICAL_SECTION相关的操作进行了封装,而mutex_pthread是对pthread_mutex_t相关操作的封装。其实在这里,我不知道作者为什么要采用这种宏的方式,我觉得完全可以能过封装一个通用的Thread类和Mutex类,这样用起来更为方便,而且要做扩展也比较容易。
[url]http://www.wuzesheng.com/?p=120[/url]
CLucene源码剖析(三) 实现跨平台的线程安全
2009年5月29日 小武哥 发表评论 阅读评论
在多线程编程中,程序的线程安全(thread-safe)是十分重要的,要做到这一点,一方面要在程序设计的过程中,尽可能设计多的单线程访问的数据结构,一方面就是合理的使用锁(Mutex)。在CLucene中,实现了如下跨平台的锁相关的宏:
(1) _LUCENE_SLEEP(x) 挂起当前线程 x微秒
(2) _LUCENE_THREADMUTEX 线程锁(mutex)
(3) _LUCENE_CURRTHREADID 获取当前线程的thread ID
(4) _LUCENE_THREADID_TYPE thread ID的类型定义
通过上面几个宏,就可以实现基本的线程安全的相关操作。下面对上述宏的具体实现进行一一详细说明:
1.在windows平台下:
(1) _LUCENE_SLEEP(x)由系统API Sleep()实现
1
#define _LUCENE_SLEEP(x) Sleep(x)
(2) _LUCENE_THREADMUTEX由CRITICAL_SECTION相关的内容实现
1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_win32
(3) _LUCENE_CURRTHREADID由系统API GetCurrentThreadId()实现
1
#define _LUCEN colla="E_CURRTHREADID GetCurrentThreadId()
(4) _LUCENE_THREADID_TYPE类型为 DWORD类型
1
#define _LUCENE_THREADID_TYPE DWORD
2.在unix平台下:
(1) _LUCENE_SLEEP(x)由系统函数 usleep()实现
1
#define _LUCENE_SLEEP(x) usleep(x*1000)
(2) _LUCENE_THREADMUTEX由pthread_mutex_t相关的内容实现
1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_pthread
(3) _LUCENE_CURRTHREADID由pthread中的pthread_self()的实现
1
#define _LUCENE_CURRTHREADID pthread_self()
(4) _LUCENE_THREADID_TYPE类型为pthread_t类型
1
#define _LUCENE_THREADID_TYPE pthread_t
从上面的讲解过程中,我们可以看出_LUCENE_THREADMUTEX的实现,还是有一层包装的,在windows下是mutex_win32,在unix下是mutex_pthread,所以要想深入理解,还需要更加深入一步。
下面是mutex_win32的实现:
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
class mutex_win32
{
private:
CRITICAL_SECTION mtx;
public:
mutex_win32(const mutex_win32& clone);
mutex_win32();
~mutex_win32();
void lock();
void unlock();
};
mutex_win32::mutex_win32(const mutex_win32& clone){
InitializeCriticalSection(&mtx);
}
mutex_win32::mutex_win32()
{
InitializeCriticalSection(&mtx);
}
mutex_win32::~mutex_win32()
{
DeleteCriticalSection(&mtx);
}
void mutex_win32::lock()
{
EnterCriticalSection(&mtx);
}
void mutex_win32::unlock()
{
LeaveCriticalSection(&mtx);
}
下面是mutex_pthread的实现:
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
class mutex_pthread
{
private:
pthread_mutex_t mtx;
public:
mutex_pthread(const mutex_pthread& clone);
mutex_pthread();
~mutex_pthread();
void lock();
void unlock();
private:
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t lockOwner;
unsigned int lockCount;
#endif
};
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
bool mutex_pthread_attr_initd=false;
pthread_mutexattr_t mutex_pthread_attr;
#endif
#ifdef _CL__CND_DEBUG
#define _CLPTHREAD_CHECK(c,m) CND_PRECONDITION(c==0,m)
#else
#define _CLPTHREAD_CHECK(c,m) c;
#endif
mutex_pthread::mutex_pthread(const mutex_pthread& clone){
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}
mutex_pthread::mutex_pthread()
{
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
if ( mutex_pthread_attr_initd == false ){
pthread_mutexattr_init(&mutex_pthread_attr);
pthread_mutexattr_settype(&mutex_pthread_attr, PTHREAD_MUTEX_RECURSIVE);
mutex_pthread_attr_initd = true;
}
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}
mutex_pthread::~mutex_pthread()
{
_CLPTHREAD_CHECK(pthread_mutex_destroy(&mtx), "~mutex_pthread destructor failed")
}
void mutex_pthread::lock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t currentThread = pthread_self();
if( pthread_equal( lockOwner, currentThread ) ) {
++lockCount;
} else {
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
lockOwner = currentThread;
lockCount = 1;
}
#else
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
#endif
}
void mutex_pthread::unlock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
--lockCount;
if( lockCount == 0 )
{
lockOwner = 0;
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
}
#else
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
#endif
}
由上面的实现可以看出,mutex_win32直接就是对CRITICAL_SECTION相关的操作进行了封装,而mutex_pthread是对pthread_mutex_t相关操作的封装。其实在这里,我不知道作者为什么要采用这种宏的方式,我觉得完全可以能过封装一个通用的Thread类和Mutex类,这样用起来更为方便,而且要做扩展也比较容易。
[url]http://www.wuzesheng.com/?p=120[/url]