《线程篇》创建线程
创建线程
参考链接: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;
}