讨论:并发控制

lianglp 2005-11-22 07:10:36
并发在多任务系统中非常重要,现代操作系统基本上是多任务的。特别作为服务器系统,如不支持多任务处理,无法想像。所以,设计一个高度并发处理的系统,

就显得犹为重要,但相对对设计人员的要求也比较高,这里,本人把平时积累的相关经验,与人家一起探讨,对这方面的问题总结其设计模式,相互学习,分享经

验。

本主题主要讨论并发控制种类,总结出至少有以下几类,为描述方面,windows系统下结合代码一起来阐述。

void A()
{
......
}

void B()
{
......
}


第一类并发控制
A、B函数自身互拆,A、B之间也互拆等等。
也就是说,只要某一个函数进入,另一函数(包含自身)都需等待,直到A函数退出。这一方面,系统本身就提供了相关的互拆API可以使用,比如EnterCriticalSe

ction(),LeaveCriticalSection()成一对,WaitForSingleObject(Mutex对象),ReleaseMutex(Mutex对象)成一对。

第二类并发控制
A函数自身不互拆(可多线程同时执行),但与B函数互拆,B函数多线程时自身也互拆。
这类并发控制主要在对读写等操作场合,比如说读操作可以同时多线程进行,而写操作只能一个一个来,同时在写的时候,不再允许有读操作。这类并发控制,其

实大家如是CS专业,在学校里应该接触过,比如生产消费者问题等等。

第三类并发控制
其实这类并发控制是第二类一个派生。有些场合,会出现下面情况:当A函数执行时,可以多线程同时执行,这一点与第二类一样,而当有B函数执行时,后继将要

执行A函数的线程将被等待(是指还没有进入A函数线程),与此同时,执行B函数的线程将等待A函数已进入的执行线程全部执行完后,再进入,这样,上面提到的

将要执行A函数的线程都将等待B执行完成后可再进入。
这里,大家可能觉得与第二类并发控制一样,其实不然。如果出现很多线程不停的调用A函数,使用第二类并发控制,B函数将很有可能得不到执行。比如说:当前A

函数有二个及以上线程同时运行,此时另一线程将要执行B函数,而B函数看到A函数在运行,将会进入等待状态,直到等待所有执行A函数线程完毕。而此时A函数如

不停有几个线程同时再次运行,这样,B函数的执行线程就永远不会得到执行。只有当B函数想要运行的时候,阻塞后继想进入A函数执行的线程,B函数才会有机会

被执行,因为在执行A函数的后继线程被执行B函数的线程阻塞了。
这就是说,此并发控制在第二类基础上增加了当执行B函数时的线程具有比执行A函数线程在进入互拆区时优先级高。

第四类并发控制
执行A函数的线程不互拆,执行B函数的线程不互拆,但是,A、B函数之间不能同时执行。
比如从一个村到另一个村需经过一条河,这条河有两座桥,桥是用铁链子拉起来然后在上边扑上木板后,行人就可以通过这座桥了。但是,由于一些原因,木板只

够一座桥,但规定,C村的人只能走A桥,D村的人只能走B桥,这样C村的行人在桥上走时,如此时D村人也想过桥就走不通了(木板都被放到A桥了),只有当C村人

全部过桥后(在过时,可能会有好几个人),再把木板弄回到B桥,D村的人才可以过。
其实这类并发控制跟这种情况就非常相似。

第五类并发控制
其实这是第四类并发控制的一个派生。跟第三类并发控制一样,具有优先级。

第六类并发控制
指定相同的标识符才互拆,否则,不互拆。

以上就是实现并发控制的几种情况,如大家有不同类型时出现的并发控制,跟上吧,接着写,下面是实现代码

//////////////////////////////////////////////
//第一类并发控制
//////////////////////////////////////////////

//进入互拆
void EnterMutex()
{
::EnterCriticalSection(&cs);
}

//离开互拆
void LeaveMutex()
{
::LeaveCriticalSection(&cs);
}


//////////////////////////////////////////////
//第二类并发控制
//////////////////////////////////////////////
void EnterMultiNoMutex()
{
::EnterCriticalSection(&cs[0]);
if(dwCounter == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter++;
::LeaveCriticalSection(&cs[0]);
}

//退出对于自身执行体不互拆的互拆区
void LeaveMultiNoMutex()
{
::EnterCriticalSection(&cs[0]);
dwCounter--;
if(dwCounter == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[0]);
}

//进入对于自身执行体互拆,对于EnterMultiNoMutex()也互拆的互拆区
void EnterMultiMutex()
{
::EnterCriticalSection(&cs[1]);
}

//退出对于自身执行体互拆,对于EnterMultiNoMutex()也互拆的互拆区
void LeaveMultiMutex()
{
::LeaveCriticalSection(&cs[1]);
}


/////////////////////////////////////////////
//第三类并发控制
/////////////////////////////////////////////
void EnterMultiNoMutexP()
{
TCHAR szEventName[MAX_PATH] = {TEXT("__ConcurrentCtrlEventName")};
if(HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS,FALSE,szEventName))
{
//如果有线程进入EnterMultiMutexP()优先代码执行区,则等待优先代码执行区退出
::WaitForSingleObject(hEvent,INFINITE);
::CloseHandle(hEvent);
}

::EnterCriticalSection(&cs[0]);
if(dwCounter[0] == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter[0]++;
::LeaveCriticalSection(&cs[0]);
}

void LeaveMultiNoMutexP()
{
::EnterCriticalSection(&cs[0]);
dwCounter[0]--;
if(dwCounter[0] == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[0]);
}

void EnterMultiMutexP()
{
::EnterCriticalSection(&cs[2]);
if(dwCounter[1] == NULL)
{
//如第一次进入,先创建优先执行的事件,以便其他线程在调用EnterMultiNoMutexP()时阻塞
TCHAR szEventName[MAX_PATH] = {TEXT("__ConcurrentCtrlEventName")};
hEvent = ::CreateEvent(NULL,TRUE,FALSE,szEventName);
::ResetEvent(hEvent);
}
dwCounter[1]++;
::LeaveCriticalSection(&cs[2]);

::EnterCriticalSection(&cs[1]);
}

void LeaveMultiMutexP()
{
::LeaveCriticalSection(&cs[1]);

::EnterCriticalSection(&cs[2]);
dwCounter[1]--;
if(dwCounter[1] == NULL)
{
//优先代码区执行完成,要放弃优先权,以便EnterMultiNoMutexP()等待的线程得到阻塞
::SetEvent(m_hEvent);
::CloseHandle(m_hEvent);
m_hEvent = NULL;
}
::LeaveCriticalSection(&cs[2]);
}




使用这些并发控制例子:
void A()
{
EnterMultiNoMutexP();

//执行自已的功能代码
......

LeaveMultNoMutexP();
}


void B()
{
EnterMultiMutexP();

//执行自已的功能代码

LeaveMultiMutexP();
}
...全文
233 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
T97102003 2005-11-22
  • 打赏
  • 举报
回复
学习
oyljerry 2005-11-22
  • 打赏
  • 举报
回复
并发控制等,就需要很好的控制好同步
mynamelj 2005-11-22
  • 打赏
  • 举报
回复
支持,先占个头位
lianglp 2005-11-22
  • 打赏
  • 举报
回复
///////////////////////////////////////////////////
//第五类并发控制
///////////////////////////////////////////////////
void EnterMultiNoMutex1P()
{
TCHAR szEventName[MAX_PATH] = {TEXT("__ConcurrentCtrl5")};
if(HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS,FALSE,szEventName))
{
//如果其它线程进入优先代码执行区,则等待优先代码执行区退出
::WaitForSingleObject(hEvent,INFINITE);
::CloseHandle(hEvent);
}

::EnterCriticalSection(&cs[0]);
if(dwCounter[0] == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter[0]++;
::LeaveCriticalSection(&cs[0]);
}

void LeaveMultiNoMutex1P()
{
::EnterCriticalSection(&cs[0]);
dwCounter[0]--;
if(dwCounter[0] == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[0]);
}

void EnterMultiNoMutex2P()
{
::EnterCriticalSection(&cs[3]);
if(dwCounter[2] == NULL)
{
TCHAR szEventName[MAX_PATH] = {TEXT("__ConcurrentCtrl5")};
m_hEvent = ::CreateEvent(NULL,TRUE,FALSE,szEventName);
::ResetEvent(m_hEvent);
}
dwCounter[2]++;
::LeaveCriticalSection(&cs[3]);

::EnterCriticalSection(&cs[2]);
if(dwCounter[1] == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter[1]++;
::LeaveCriticalSection(&cs[2]);
}

void LeaveMultiNoMutex2P()
{
::EnterCriticalSection(&cs[2]);
dwCounter[1]--;
if(dwCounter[1] == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[2]);

::EnterCriticalSection(&cs[3]);
dwCounter[2]--;
if(dwCounter[2] == NULL)
{
::SetEvent(m_hEvent);
::CloseHandle(m_hEvent);
m_hEvent = NULL;
}
::LeaveCriticalSection(&cs[3]);
}
lianglp 2005-11-22
  • 打赏
  • 举报
回复
///////////////////////////////////////////////////
//第四类并发控制
///////////////////////////////////////////////////
void EnterMultiNoMutex1()
{
::EnterCriticalSection(&cs[0]);
if(dwCounter0] == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter[0]++;
::LeaveCriticalSection(&cs[0]);
}

void LeaveMultiNoMutex1()
{
::EnterCriticalSection(&m_csForType4[0]);
dwCounter[0]--;
if(dwCounter[0] == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[0]);
}

void EnterMultiNoMutex2()
{
::EnterCriticalSection(&cs[2]);
if(dwCounter[1] == NULL)
{
::EnterCriticalSection(&cs[1]);
}
dwCounter[1]++;
::LeaveCriticalSection(&cs[2]);
}

void LeaveMultiNoMutex2()
{
::EnterCriticalSection(&cs[2]);
dwCounter[1]--;
if(dwCounter[1] == NULL)
{
::LeaveCriticalSection(&cs[1]);
}
::LeaveCriticalSection(&cs[2]);
}





18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧