《线程篇》创建线程

创建线程

参考链接: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 // 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

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

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

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

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

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  阅读(51)  评论(0)    收藏  举报