临界区,互斥量,信号量,事件多线程总结

首先是创建一个线程,注意CreateThread和_beginthreadex的区别,后者在程序中含有C语言库的情况下一样安全使用。C语言库在编写的时候没有考虑到多线程,Windows中通过创建专用内存区来解决这个问题(由_beginthreadex创建)。

CreateThread和_beginthreadex参数一样,后者最终是调用前者创建线程的。

CreatThread(安全性(NULL),堆栈大小(0),函数地址(函数名字),传入参数(i),创建后状态(0),返回线程ID(NULL))

这时前者配套的函数形式DWORD WINAPI ThreadFunc(LPVOID pm)

后者配套的函数形式unsigned int __stdcall ThreadFunc(void* pm)


临界区:

注意不可以跨进程使用,不是内核对象,占用资源比较少,”线程所有权问题“只能解决”互斥问题“不可以解决“同步问题”

CRITICAL_SECTION g_csThread;//创建临界区
InitializeCriticalSection(&g_csThread)//使用前初始化临界区
EnterCriticalSection(&g_csThread)//进入临界区
LeaveCriticalSection(&g_csThread)//离开临界区
DeleteCriticalSection(&g_csThread)//用完了删除临界区


互斥量

同临界区很像,但是它是内核对象,可以跨进程使用;”线程所有权问题“只能解决”互斥问题“不可以解决“同步问题”

HANDLE handleMutex=CreateMutex(安全性(NULL),是否为当前进程所有(True),名称(NULL))
ReleaseMutex(handle);//释放资源
WaitForSingleObject(handle,INFINITE);//等待资源


信号量

内核对象,可以解决同步问题

CreateSemaphore(安全性(NULL),初始资源数量,最大并发数,名称(NULL));//创建信号量
<pre name="code" class="cpp">WaitForSingleObject(handle,INFINITE);//等待资源
ReleaseSemaphore(句柄,增加个数,传出之前计数(NULL));OpenSemaphore(访问权,继承性,名称);
 


事件

内核对象,可以解决同步问题

CreateEvent(安全性(NULL),是否手动(FALSE(自动)),初始状态(TRUE为触发),事件名称(NULL));
OpenEvent(访问权,继承性,名称);
SetEvent(句柄);
ResetEvent(句柄);

下面是一个用事件实现ABC交替执行的程序,是一个面试题,3个进程,交替执行ABC...

#include<cstdio>
#include<windows.h>
#include<process.h>
unsigned int __stdcall Fun(void* pm);

const int ThreadNum=3;
const int LOOP=10;
HANDLE g_hTreadEvent[ThreadNum];

void main()
{
	printf("ABC...交替执行!\n");
	int i=0;
	HANDLE handle[ThreadNum];

	for(i=0; i<ThreadNum; i++)
		g_hTreadEvent[i]=CreateEvent(NULL,FALSE,FALSE,NULL);

	for(i=0; i<ThreadNum; i++)
		handle[i]=(HANDLE)_beginthreadex(NULL,0,Fun,(void*)i,0,NULL);

	SetEvent(g_hTreadEvent[0]);

	WaitForMultipleObjects(ThreadNum,handle,TRUE,INFINITE);
	for(i=0;i<ThreadNum;i++)
	{
		CloseHandle(handle[i]);
		CloseHandle(g_hTreadEvent);
	}

}
unsigned int __stdcall Fun(void* pm)
{
	int num=(int)(pm);
	for(int i=0; i<LOOP;i++)
	{
	   WaitForSingleObject(g_hTreadEvent[num],INFINITE);
	   printf(" %c ",num+'A'); 
	   if(num+1==ThreadNum)
		   printf("\n");
	   SetEvent(g_hTreadEvent[(num+1)%ThreadNum]);//%ThreadNum
	}

	return 0;

}




事件,临界区和互斥量,信号量都可以解决单生产者,消费者,缓冲区

多生产者,消费者,缓冲区,信号量解决最好

下面是事件解决单生产者,消费者,缓冲区

//1生产者 1消费者 1缓冲区
//使用二个事件,一个表示缓冲区空,一个表示缓冲区满。
//再使用一个关键段来控制缓冲区的访问
#include <stdio.h>
#include <process.h>
#include <windows.h>
//设置控制台输出颜色
BOOL SetConsoleColor(WORD wAttributes)
{
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hConsole == INVALID_HANDLE_VALUE)
                return FALSE;        
        return SetConsoleTextAttribute(hConsole, wAttributes);
}
const int END_PRODUCE_NUMBER = 10;   //生产产品个数
int g_Buffer;                        //缓冲区
//事件与关键段
CRITICAL_SECTION g_cs;
HANDLE g_hEventBufferEmpty, g_hEventBufferFull;
//生产者线程函数
unsigned int __stdcall ProducerThreadFun(PVOID pM)
{
        for (int i = 1; i <= END_PRODUCE_NUMBER; i++)
        {
                //等待缓冲区为空
                WaitForSingleObject(g_hEventBufferEmpty, INFINITE);

                //互斥的访问缓冲区
                EnterCriticalSection(&g_cs);
                g_Buffer = i;
                printf("生产者将数据%d放入缓冲区\n", i);
                LeaveCriticalSection(&g_cs);
                
                //通知缓冲区有新数据了
                SetEvent(g_hEventBufferFull);
        }
        return 0;
}
//消费者线程函数
unsigned int __stdcall ConsumerThreadFun(PVOID pM)
{
        volatile bool flag = true;
        while (flag)
        {
                //等待缓冲区中有数据
                WaitForSingleObject(g_hEventBufferFull, INFINITE);
                
                //互斥的访问缓冲区
                EnterCriticalSection(&g_cs);
                SetConsoleColor(FOREGROUND_GREEN);
                printf("  消费者从缓冲区中取数据%d\n", g_Buffer);
                SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                if (g_Buffer == END_PRODUCE_NUMBER)
                        flag = false;
                LeaveCriticalSection(&g_cs);
                
                //通知缓冲区已为空
                SetEvent(g_hEventBufferEmpty);

                Sleep(10); //some other work should to do
        }
        return 0;
}
int main()
{
        printf("  生产者消费者问题   1生产者 1消费者 1缓冲区\n");
        printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");

        InitializeCriticalSection(&g_cs);
        //创建二个自动复位事件,一个表示缓冲区是否为空,另一个表示缓冲区是否已经处理
        g_hEventBufferEmpty = CreateEvent(NULL, FALSE, TRUE, NULL);
        g_hEventBufferFull = CreateEvent(NULL, FALSE, FALSE, NULL);
        
        const int THREADNUM = 2;
        HANDLE hThread[THREADNUM];
        
        hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL);
        hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL);
        WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
        CloseHandle(hThread[0]);
        CloseHandle(hThread[1]);
        
        //销毁事件和关键段
        CloseHandle(g_hEventBufferEmpty);
        CloseHandle(g_hEventBufferFull);
        DeleteCriticalSection(&g_cs);
        return 0;
}

代码来自http://www.itmian4.com/forum.php?mod=forumdisplay&fid=94&filter=typeid&typeid=127

推荐一下很好的一个网站!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值