多线程学习笔记

一、摘要

1.线程函数

DWORD WINAPI threadname(LPVOID lpParamter) // 函数名字可随意
{
	int *a = (int *)lpParamter;
	return 0L;
}

2.创建线程

HANDLE hThread = CreateThread(NULL, 0, threadname, NULL, 0, NULL);

3.等待线程

WaitForSingleObject(hThread , INFINITE);

4.互斥量

HANDLE cout_mutex;
cout_mutex = CreateMutex(NULL, FALSE, NULL);

WaitForSingleObject(cout_mutex, INFINITE);
ReleaseMutex(cout_mutex);

二、内容

1. CreateThread()

//返回值:一个HANDLE类型的值,表示线程的句柄,可用于等待线程等函数
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes, // 不重要,一般设置为NULL
  SIZE_T                  dwStackSize,        // 堆栈大小,不重要,一般设置为0,表示使用默认堆栈大小
  LPTHREAD_START_ROUTINE  lpStartAddress,     // 函数指针,传入函数名或指针即可
  __drv_aliasesMem LPVOID lpParameter,        // 参数指针,供函数使用
  DWORD                   dwCreationFlags,    // 不重要,一般设置为0
  LPDWORD                 lpThreadId          // 指针,用于保存线程的id,一般设置为NULL
);]

使用方法1:无参数多线程函数

DWORD WINAPI threadname(LPVOID lpParamer)
{
//do something

return 0L;
}

HANDLE hThread = CreateThread(NULL,0,threadname,NULL,0,MULL)

使用方法2:有参多线程函数:lpParameter参数

  概念: 

 lpParamter 跟 void指针使用方法类似,void指针可以指向任何数据,所以我们可以把任何类形指针的值赋给void指针(但不能把void指针的值直接赋给其它类型的指针!)

int a = 0;

int *intp = &a;

// int指针 转 void指针

void * voidp = intp; // 合法!不会报错

实例:

DWORD WINAPI MyThread(LPVOID lpParamter)
{
	// 把lpParamter当成void指针就完事儿了
	int *a = (int *)lpParamter;

	cout << "I have " << a[0] << " dolors!\n";
	return 0L;
}


//而创造函数时候,传入一个整形指针就行了

int main ()
{
	int a = 0;
	int *p = &a;
	// 创造线程,注意我把p指针作为参数传入了,它也就成为了上方函数的lpParamter
	CreateThread(NULL, 0, MyThread, p, 0, NULL);
	// 记得等待线程结束
	system("PAUSE");
	return 0;
}


至于传入更多的参数,可以自己设计一个struct或者class数据结构,并传入其指针就行了,或者也可以传入数组。
至于返回值,也可以利用传入的指针来接收。

2.等待指定线程结束:WaitForSingleObject()

     (1)这个特别简单,此函数就两个参数,第一个参数是创建线程时可得到的返回值(HANDLE)也就是句柄,第二个参数不用关心,传入INFINITE就行了。

     (2)如果事件是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT。

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

使用实例:

//函数声明
DWORD WaitForSingleObject(HANDLE hHandle , DWORD dwMilliseconds);

//参数1:可以传入句柄,监控线程;可以传入Event对象,控制线程运行状态;
//参数2:0代表立即返回;INFINITE代表线程一直挂起;填入数值则超时退出
返回值        含义 
WAIT_FAILED     函数失败 
WAIT_OBJECT_0    指定的同步对象处于有信号的状态 
WAIT_ABANDONED  拥有一个mutex的线程已经中断了,但未释放该MUTEX 
WAIT_TIMEOUT    超时返回,并且同步对象无信号 





HANDLE hThread = CreateThread(NULL, 0, thread1, NULL, 0, NULL);
// 利用得到的句柄等待线程结束
WaitForSingleObject(hThread, INFINITE);

有了这个函数,再也不用Sleep或者While(1)啦。

 

3.多线程资源加锁:CreateMutex()

1.概念

(1)声明

1.声明

HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
BOOL bInitialOwner, // 初始化互斥对象的所有者
LPCTSTR lpName // 指向互斥对象名的指针
);

2.创建

//只是创建了一把锁, 到目前这句完成, 他没有锁任何东西。
HANDLE m_hMutex = CreateMutex(NULL,TRUE,"cplusplus_me");   

3.使用
//从线程函数开始加锁 ,到线程函数结束时解锁

//加锁
WaitForSingleObject(hMutex, INFINITE); 

//这里写被加锁的东西.  一般是操作一些共享数据(占用系统内存)。

//解锁
ReleaseMutex(hMutex);

(2)调用

HANDLE m_hMutex = CreateMutex(NULL,TRUE,"cplusplus_me");   只是创建了一把锁, 到目前这句完成, 他没有锁任何东西。

 

2.为资源加锁:

 

创建方法:

// 声明一个句柄
HANDLE cout_mutex;
// 创建一个锁
cout_mutex = CreateMutex(NULL, FALSE, NULL);

使用方法:

// 等待其它线程释放锁,并获取锁的使用权
WaitForSingleObject(cout_mutex, INFINITE);

// 获取锁之后,只要没有解锁,其它线程就会阻塞在WaitForSingleObject()语句。
做一些工作(使用需要互斥的资源等)

// 解锁!
ReleaseMutex(cout_mutex);

使用例子:

HANDLE cout_mutex;

DWORD WINAPI MyThread(LPVOID lpParamter)
{
	// 把lpParamter当成void指针就完事儿了
	int *a = (int *)lpParamter;
	WaitForSingleObject(cout_mutex, INFINITE);
	cout << "I have " << a[0] << " dolors!" << endl;
	ReleaseMutex(cout_mutex);
	return 0L;
}

int main()
{
	int a[10];
	cout_mutex = CreateMutex(NULL, FALSE, NULL);
	for (int i = 0; i < 10; i++)
	{
		a[i] = i;
		HANDLE hThread = CreateThread(NULL, 0, MyThread, a + i, 0, NULL);
	}
	system("PAUSE");
	return 0;
}

运行结果:

可以看出输出正常了。

I have 0 dolors!
I have 1 dolors!
I have 7 dolors!
I have 5 dolors!
I have 4 dolors!
I have 6 dolors!
I have 3 dolors!
I have 9 dolors!
I have 2 dolors!
 

4.指定线程运行核心:SetThreadAffinityMask()

函数声明
DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask);

使用方法:
第一个参数是线程的句柄(HANDLE),第二个参数用来指定CPU核心

比如,你要指定进程到第0个CPU上,则mask=0×01
第1个CPU:mask=0×02
第2个CPU:mask=0×04 (注意不是0×03)
第3个CPU:mask=0×08

3.代码实例:

// 绑定到第三个核心
HANDLE hThread = CreateThread(NULL, 0, MyThread, a + i, 0, NULL);
SetThreadAffinityMask(hThread, 0x08);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值