Windows多线程总结(3)-- 线程同步(使用互斥对象实现线程同步)

         上一篇说明了多线程是存在着问题的,起始就是多线程操作同一数据而不同步的问题。那么如果实现线程的同步呢?

         线程的同步有多种实现方式:

        互斥内核对象、事件内核对象、可等待的计数器内核对象、信号量内核对象和等待函数等等来实现线程的同步。

        我们先用互斥内核对象实现线程同步。

      

         互斥内核对象,能够确保线程拥有对单个资源的互斥访问权,互斥对象包含一个使用数量,一个线程ID和一个计数器。其中ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。

使用CreateMutext函数,创建或打开一个互斥对象,然后利用互斥对象完成线程间的同步。

HANDLE CreateMutex(
     LPSECURITY_ATTRIBUTESl  pMutexAttributes, // 指向安全属性的指针
     BOOL  bInitialOwner, // 初始化互斥对象的所有者
     LPCTSTR  lpName // 指向互斥对象名的指针
);
参数 类型及说明
lpMutexAttributes :

         可以使用NULL,表示使用默认的安全性。
bInitialOwner
:

          表示互斥对象的初始拥有者。如果为真,创建这个互斥对象的线程获得该对象的所有权,否则,该线程不获得该互斥对象的所有权。
lpName
:

          指定互斥体对象的名字。如果为NULL,则创建一个匿名的互斥对象。


       当结束后,使用ReleaseMutex函数进行释放指定对象的所有权。

BOOL WIANPI ReleaseMutex(
    HANDLE hMutex
);

      需要注意,线程只有主动请求共享对象的所有权才有可能获取到该所有权,我们可以通过WaitForSingleObject来实现

DWORD WaitForSingleObject(
     HANDLE hHandle,
     DWORD dwMilliseconds
);
         hHandle为句柄,此处为 hMutex的句柄,

        dwMilliseconds为指定时间间隔,单位为毫秒。如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。

       WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

   

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <windows.h>

int tickets = 100;
HANDLE hMutex;
int idx = 0;

DWORD  WINAPI ThreadProc1(LPVOID lpThreadParameter)
{

	while (TRUE)
	{
		WaitForSingleObject(hMutex, INFINITE);
		if (tickets>0)
		{
			Sleep(1);
			printf("thread1 ----  %d \n", tickets--);
		}
		else
		{
			break;
		}

		ReleaseMutex(hMutex);
	}
	return 0;
}


DWORD  WINAPI ThreadProc2(LPVOID lpThreadParameter)
{

	while (TRUE)
	{
	 	WaitForSingleObject(hMutex, INFINITE);
		if (tickets > 0)
		{
			Sleep(1);
			printf("thread2 ----  %d \n", tickets--);
		}
		else
		{
			break;
		}
		ReleaseMutex(hMutex);

	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
 
	//创建线程
	HANDLE  h1 = CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	HANDLE  h2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);

	CloseHandle(h1);
	CloseHandle(h2);


	//创建互斥对象
	hMutex = CreateMutex(NULL, FALSE, NULL);
	/*<pre name="code" class="html">        hMutex = CreateMutex(NULL, TRUE, NULL);  //如果第二个参数设置为true 那么此时互斥对象为主线程所有  
ReleaseMutex(hMutex); //当第二参数的为True的时候 则需要使用该函数 进行释放互斥对象 只有释放后线程1和线程2才能获取 */system("pause");return 0;}


阅读更多
个人分类: 多线程
上一篇Windows多线程总结(2)-- 多线程的使用
下一篇Windows多线程总结(4)-- 线程同步(使用互斥对象实现线程同步 只运行一个对象)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭