您的位置:首页 > 其它

线程通知MFC多线程程序的同步机制

2013-04-29 13:43 363 查看
间时紧张,先记一笔,后续优化与完善。

简介

本文讨探基本的步同念概,并现实着手帮助新手握掌多线程程编。本文的重点在各种步同巧技。

基本念概

在线程执行过程当中,或多或少都要需彼此互交,种这互交行为有多种形式和类型。例如,一个线程在执行完它被予赋的任务后,通知另一个线程任务经已成完。然后第二个线程做开始剩下的任务。

下述对象是用来支撑步同的:

1)信号量

2)互斥锁

3)症结区域

4)件事

每一个对象都有不同的目标和用处,但基本目标都是支撑步同。当然还有其他可以用来步同的对象,比如进程和线程对象。后两者的应用由程序员决议,比如说判断一个给定进程或线程是不是执行毕完为了应用进程和线程对象来行进步同,我们一般应用Wait*函数,在应用这些函数时,你该应晓得一个念概,任何被作为步同对象的内核对象(症结区域除外)都处于两种态状之一:通知态状和未通知态状。例如,进程和线程对象,当他们开始执行时处于未通知态状,而当他们执行毕完时处于通知态状,

为了判断一个给定进程或线程是不是经已结束,我们必须判断示表其的对象是不是处于通知态状,而要到达这样的目标,我们要需应用Wait*函数。

Wait*函数

面上是最简略的Wait*函数:

DWORD WaitForSingleObject
(
HANDLE hHandle,
DWORD dwMilliseconds
);

数参hHandle示表待查检其态状(通知或者未通知)的对象,dwMilliseconds示表用调线程在被查检对象进入其通知态状前该应等待的间时。若对象处于通知态状或指定间时过去了,这个函数返回制控权给用调线程。若dwMilliseconds置设为INIFINITE(值为-1),则用调线程会直一等待直到对象态状变成通知,这有可能使得用调线程永久等待下去,致导“饿死”。

例如,查检指定线程是不是正在执行, dwMilliseconds置设为0,是为了让用调线程马上返回。

DWORD dw
=
WaitForSingleObject(hProcess,
0
);

switch
(dw)

DWORD WaitForMultipleObjects
(
DWORD nCount,
CONST HANDLE
*
lpHandles,
BOOL fWaitAll,
DWORD dwMilliseconds
);

HANDLE h[
3
];
h[
0
]
=
hThread1;
h[
1
]
=
hThread2;
h[
2
]
=
hThread3;

DWORD dw
=
WaitForMultipleObjects(
3
, h, FALSE,
5000
);
//
任何一个进入已通知就返回

switch
(dw)

//
create an auto-reset event

CEvent g_eventStart;

UINT ThreadProc1(LPVOID pParam)
UINT ThreadProc2(LPVOID pParam)

//
create a manual-reset event

CEvent g_eventStart(FALSE, TRUE);

UINT ThreadProc1(LPVOID pParam)

UINT ThreadProc2(LPVOID pParam)

struct
THREADINFO

UINT ThreadDraw(PVOID pParam);

extern
CEvent g_eventEnd;

UINT ThreadDraw(PVOID pParam)

CArray
<
CWinThread
*
, CWinThread
*>
m_ThreadArray;
//
存保CWinThread对象指针

//
manual-reset event

CEvent g_eventEnd(FALSE, TRUE);

void
CWorkerThreadsView::OnLButtonDown(UINT nFlags, CPoint point)

void
CWorkerThreadsView::OnDestroy()

int
g_nVariable
=

0
;

UINT Thread_First(LPVOID pParam)

UINT Thread_Second(LPVOID pParam)

CCriticalSection g_cs;

int
g_nVariable
=

0
;

UINT Thread_First(LPVOID pParam)

UINT Thread_Second(LPVOID pParam)

class
CSomeClass

CSingleLock singleLock(
&
m_Mutex);
singleLock.Lock();
//
try to capture the shared resource

if
(singleLock.IsLocked())
//
we did it

或者通过Win32函数:

//
try to capture the shared resource

::WaitForSingleObject(m_Mutex, INFINITE);

//
use the shared resource

//
After we done, let other threads use the resource

::ReleaseMutex(m_Mutex);

HANDLE h
=
CreateMutex(NULL, FALSE,
"
MutexUniqueName
"
);

if
(GetLastError()
==
ERROR_ALREADY_EXISTS)

CSemaphore g_Sem(
5
,
5
);

一旦线程访问共享资源,信号量的计数器就减1.若变成0,则接来下对资源的访问会被拒绝,直到有一个持有资源的线程离开(也就是说释放了信号量)。我们可以如下应用:

//
Try to use the shared resource

::WaitForSingleObject(g_Sem, INFINITE);

//
Now the user's counter of the semaphore has decremented by one

//
Use the shared resource

//
After we done, let other threads use the resource

::ReleaseSemaphore(g_Sem,
1
, NULL);

//
Now the user's counter of the semaphore has incremented by one

#define
WM_MYMSG WM_USER + 1

这只能保证口窗类中唯一,但为了保确整个应用程序中唯一,更为安全的方式是:

#define
WM_MYMSG WM_APP + 1

afx_msg LRESULT OnMyMessage(WPARAM , LPARAM );

LRESULT CMyWnd::OnMyMessage(WPARAM wParam, LPARAM lParam)

BEGIN_MESSAGE_MAP(CMyWnd, CWnd)

ON_MESSAGE(WM_MYMSG, OnMyMessage)
END_MESSAGE_MAP()

UINT ThreadProc(LPVOID pParam)




但这个方法有个很大的缺陷--内存泄漏,作者没有深入研究,可以参考我这篇文章《浅谈一个线程通信代码的内存泄漏及解决方案
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: