《线程篇》创建线程

创建线程

参考链接:https://www.jb51.net/article/233512.htm
参考链接:https://blog.csdn.net/sinat_31608641/article/details/103326497
(没有试过可行性,也没看完)

1使用使用_beginthreadex()

需要头文件#include <process.h>
需要的设置:ProjectàSetting-->C/C++-->User run-time library 选择Debug Multithreaded 或者Multithreaded。即使用: MT或MTD。

代码如下:

#include <stdio.h>
#include <string>             // for STL string class
#include <windows.h>          // for HANDLE
#include <process.h>          // for _beginthread()
using namespace std;

class ThreadX
{
private:
  int loopStart;
  int loopEnd;
  int dispFrequency;
public:
  string threadName;

  ThreadX( int startValue, int endValue, int frequency )
  {
	loopStart = startValue;
	loopEnd = endValue;
	dispFrequency = frequency;
  }

  static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)
  {
	  ThreadX * pthX = (ThreadX*)pThis;   // the tricky cast
	  pthX->ThreadEntryPoint();           // now call the true entry-point-function
	  return 1;                              // the thread exit code
  }

  void ThreadEntryPoint()
  {
	for (int i = loopStart; i <= loopEnd; ++i)
	{
	  if (i % dispFrequency == 0)
	  {
		  printf( "%s: i = %d\n", threadName.c_str(), i );
	  }
	}
	printf( "%s thread terminating\n", threadName.c_str() );
  }
};


int main()
{
	ThreadX * o1 = new ThreadX( 0, 1, 2000 );

	HANDLE   hth1;
	unsigned  uiThread1ID;

	hth1 = (HANDLE)_beginthreadex( NULL,         // security
					0,            // stack size
					ThreadX::ThreadStaticEntryPoint,
					o1,           // arg list
					CREATE_SUSPENDED,  // so we can later call ResumeThread()
					&uiThread1ID );

	if ( hth1 == 0 )
		printf("Failed to create thread 1\n");

	DWORD   dwExitCode;
	GetExitCodeThread( hth1, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
	printf( "initial thread 1 exit code = %u\n", dwExitCode );

	o1->threadName = "t1";

	ThreadX * o2 = new ThreadX( -100000, 0, 2000 );

	HANDLE   hth2;
	unsigned  uiThread2ID;

	hth2 = (HANDLE)_beginthreadex( NULL,         // security
				0,            // stack size
				ThreadX::ThreadStaticEntryPoint,
				o2,           // arg list
				CREATE_SUSPENDED,  // so we can later call ResumeThread()
				&uiThread2ID );

	if ( hth2 == 0 )
		printf("Failed to create thread 2\n");

	GetExitCodeThread( hth2, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
	printf( "initial thread 2 exit code = %u\n", dwExitCode );

	o2->threadName = "t2";

	ResumeThread( hth1 );   // serves the purpose of Jaeschke's t1->Start()
	ResumeThread( hth2 );   

	WaitForSingleObject( hth1, INFINITE );
	WaitForSingleObject( hth2, INFINITE );

	GetExitCodeThread( hth1, &dwExitCode );
	printf( "thread 1 exited with code %u\n", dwExitCode );

	GetExitCodeThread( hth2, &dwExitCode );
	printf( "thread 2 exited with code %u\n", dwExitCode );

	CloseHandle( hth1 );
	CloseHandle( hth2 );

	delete o1;
	o1 = NULL;

	delete o2;
	o2 = NULL;

	printf("Primary thread terminating.\n");
	return 0;
}

多线程的同步互斥机制

参考链接:https://www.cnblogs.com/yrm1160029237/p/10207571.html

在WIN32中,同步机制主要有以下几种:
(1)事件(Event);用来通知线程有一些事件已发生,从而启动后继任务的开始。
(2)信号量(semaphore);为控制一个具有有限数量用户资源而设计。
(3)互斥量(mutex);为协调共同对一个共享资源的单独访问而设计的。
(4)临界区(Critical section)。通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。

InitializeCriticalSection(&Critical);               //初始化临界区对象
hEvent = CreateEvent(NULL, FALSE, TRUE, "event");      //初始化事件
hSemaphore = CreateSemaphore(NULL, 1, 100, "sema");    //初始化信号量
hMutex = CreateMutex(NULL, false, "mutex");             //创建互斥对象

临界区资源

临界区(Critical Section)是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。

#include "stdafx.h"
#include<windows.h>
#include<iostream>
using namespace std;

int number = 1; //定义全局变量
CRITICAL_SECTION Critical;      //定义临界区句柄

unsigned long __stdcall ThreadProc1(void* lp)
{
	while (number < 100)
	{
		EnterCriticalSection(&Critical);//标识一个临界区。
		cout << "thread 1 :"<<number << endl;
		++number;
		_sleep(100);
		LeaveCriticalSection(&Critical);//释放一个临界区
	}

	return 0;
}

unsigned long __stdcall ThreadProc2(void* lp)
{
	while (number < 100)
	{
		EnterCriticalSection(&Critical);
		cout << "thread 2 :"<<number << endl;
		++number;
		_sleep(100);
		LeaveCriticalSection(&Critical);
	}

	return 0;
}

int main()
{
	InitializeCriticalSection(&Critical);   //初始化临界区对象

	CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);

	Sleep(10*1000);

	system("pause");
	return 0;
}

事件

事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
(1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。 //SetEvent把指定的事件对象设置为有信号状态,ResetEvent把指定的事件对象设置为无信号状态
(2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。

使用”事件”机制应注意以下事项:
(1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
(2)事件是否要自动恢复;
(3)事件的初始状态设置。

#include "stdafx.h"
#include<windows.h>
#include<iostream>
using namespace std;

int number = 1; //定义全局变量
HANDLE hEvent;  //定义事件句柄

unsigned long __stdcall ThreadProc1(void* lp)
{
	while (number < 100)
	{
		WaitForSingleObject(hEvent, INFINITE);  //等待对象为有信号状态
		cout << "thread 1 :"<<number << endl;
		++number;
		_sleep(100);
		SetEvent(hEvent);//将事件对象置为有信号状态
	}

	return 0;
}

unsigned long __stdcall ThreadProc2(void* lp)
{
	while (number < 100)
	{
		WaitForSingleObject(hEvent, INFINITE);  //等待对象为有信号状态
		cout << "thread 2 :"<<number << endl;
		++number;
		_sleep(100);
		SetEvent(hEvent);//将事件对象置为有信号状态
	}

	return 0;
}

int main()
{
	CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
	hEvent = CreateEvent(NULL, FALSE, TRUE, "event");

	Sleep(10*1000);

	system("pause");
	return 0;
}

信号量

信号量是维护0到指定最大值之间的同步对象。信号量状态在其计数大于0时是有信号的,而其计数是0时是无信号的。信号量对象在控制上可以支持有限数量共享资源的访问。

信号量的特点和用途可用下列几句话定义:
(1)如果当前资源的数量大于0,则信号量有效;
(2)如果当前资源数量是0,则信号量无效;
(3)系统决不允许当前资源的数量为负值;
(4)当前资源数量决不能大于最大资源数量。

//创建信号量
HANDLE CreateSemaphore (
   PSECURITY_ATTRIBUTE psa, //信号量的安全属性
   LONG lInitialCount,     //开始时可供使用的资源数
   LONG lMaximumCount,     //最大资源数
   PCTSTR pszName);             //信号量的名称

//释放信号量
BOOL WINAPI ReleaseSemaphore(
   HANDLE hSemaphore,       //要增加的信号量句柄
   LONG lReleaseCount,     //信号量的当前资源数增加lReleaseCount
   LPLONG lpPreviousCount  //增加前的数值返回
   );


//打开信号量
 HANDLE OpenSemaphore (
   DWORD fdwAccess,      //access
   BOOL bInherithandle,  //如果允许子进程继承句柄,则设为TRUE
   PCTSTR pszName      //指要打开的对象的名字
  );

例子:

#include "stdafx.h"
#include<windows.h>
#include<iostream>
using namespace std;

int number = 1; //定义全局变量
HANDLE hSemaphore;  //定义信号量句柄

unsigned long __stdcall ThreadProc1(void* lp)
{
	long count;
	while (number < 100)
	{
		WaitForSingleObject(hSemaphore, INFINITE);  //等待信号量为有信号状态
		cout << "thread 1 :"<<number << endl;
		++number;
		_sleep(100);
		ReleaseSemaphore(hSemaphore, 1, &count);
	}

	return 0;
}

unsigned long __stdcall ThreadProc2(void* lp)
{
	long count;
	while (number < 100)
	{
		WaitForSingleObject(hSemaphore, INFINITE);  //等待信号量为有信号状态
		cout << "thread 2 :"<<number << endl;
		++number;
		_sleep(100);
		ReleaseSemaphore(hSemaphore, 1, &count);
	}

	return 0;
}

int main()
{
	hSemaphore = CreateSemaphore(NULL, 1, 100, "sema");

	CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);

	Sleep(10*1000);

	system("pause");
	return 0;
}

互斥量/互锁

采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
eg1:

#include "stdafx.h"
#include<windows.h>
#include<iostream>
using namespace std;

int number = 1; //定义全局变量
HANDLE hMutex;  //定义互斥对象句柄

unsigned long __stdcall ThreadProc1(void* lp)
{
	while (number < 100)
	{
		WaitForSingleObject(hMutex, INFINITE);
		cout << "thread 1 :"<<number << endl;
		++number;
		_sleep(100);
		ReleaseMutex(hMutex);
	}

	return 0;
}

unsigned long __stdcall ThreadProc2(void* lp)
{
	while (number < 100)
	{
		WaitForSingleObject(hMutex, INFINITE);
		cout << "thread 2 :"<<number << endl;
		++number;
		_sleep(100);
		ReleaseMutex(hMutex);
	}

	return 0;
}

int main()
{
	hMutex = CreateMutex(NULL, false, "mutex");     //创建互斥对象

	CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);

	Sleep(10*1000);

	system("pause");
	return 0;
}

eg2:

#include <iostream>
#include <windows.h>
using namespace std;

HANDLE hMutex;

DWORD WINAPI Fun(LPVOID lpParamter)//线程定义
{
	while (1) {

		//申请得到该资源:hMutex指定所申请的资源的句柄,INFINITE,表示如果没有申请到资源就一直等待该资源
		WaitForSingleObject(hMutex, INFINITE);

		cout << "Fun display!" << endl;
		Sleep(1000);

		//该函数用于释放一个独占资源,进程一旦释放该资源,该资源就不再属于它了
		ReleaseMutex(hMutex);
	}
}

int main()
{
	HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);//开启线程

	//创造了一个名为screen并且归属于创建它的进程的资源
	hMutex = CreateMutex(NULL, FALSE, L"screen");

	CloseHandle(hThread);
	while (1) {

		//申请得到该资源:hMutex指定所申请的资源的句柄,INFINITE,表示如果没有申请到资源就一直等待该资源
		WaitForSingleObject(hMutex, INFINITE);

		cout << "main display!" << endl;
		Sleep(2000);

		//该函数用于释放一个独占资源,进程一旦释放该资源,该资源就不再属于它了
		ReleaseMutex(hMutex);
	}

	return 0;
}
posted @ 2023-05-06 14:54  Fusio  阅读(18)  评论(0编辑  收藏  举报