1、回调函数
回调函数实际上就是定义一个带有函数指针参数的函数,在调用函数时,在函数中会使用函数指针指向的函数,该函数将会将运行结果返回给原函数中。
注:因为类成员函数中自带一个隐含的this指针,C++通过向其他成员函数传递一个指向自身的指针来实现程序函数访问C++数据成员。所以实现类成员函数作为回调函数有两种途径:1、不能使用成员函数 2、使用静态成员函数
如果类内成员函数调用回调函数怎么实现呢?一般有两种方法:
1.回调函数声明在类外,全局的
传类对象指针给回调函数即可使用类内成员,因为回调函数是全局的所以影响了类的封装性
2.类内成员函数作为回调函数
利用关键名static声明类内成员函数,因为类静态成员函数只能操作类静态成员,所以函数若想访问类成员,只能通过调用函数传递类对象指针给回调函数,或者在类内声明一个静态指针,该指针指向类,然后在函数中调用该指针访问类成员。
简单函数回调
#include <iostream>
#include<stdio.h>
using namespace std;
int add(int a,int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int callbackFun(int a, int b, int fp(int, int))
{
return fp(a, b);
}
int main()
{
cout << callbackFun(2, 2,add)<<endl;
cout << callbackFun(2, 2,sub) << endl;
return 0;
}
简单函数回调的另一种写法
#include <iostream>
#include<stdio.h>
using namespace std;
typedef int(*Fp)(int a, int b);
int add(int a,int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int callbackFun(int a, int b, Fp fp)
{
return fp(a, b);
}
int main()
{
cout << callbackFun(2, 2,add)<<endl;
cout << callbackFun(2, 2,sub) << endl;
return 0;
}
2、线程同步
为解决线程同步,一般来说都是使用信号量或者事件
线程互斥控制的话,主要是临界区和互斥对象
事件同步代码示例,通过使用临界区互斥访问全局变量,使用事件唤醒的方式,使另一个线程从wait状态到运行状态转变
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string.h>
#include<tchar.h>
#include<wtypes.h>
using namespace std;
DWORD WINAPI ThreadProc(LPVOID lpParam);
DWORD WINAPI ThreadProc2(LPVOID lpParam);
DWORD g_dwThreadID;
DWORD g_dwThreadID2;
UINT g_nTickets = 15;
HANDLE g_hEvent1 = NULL;
HANDLE g_hEvent2 = NULL;
CRITICAL_SECTION g_cs;
int ThreadCount = 0;
int main(int argc,_TCHAR* argv[])
{
cout << "Main thread is running:" << endl;
InitializeCriticalSection(&g_cs);//初始化临界区
HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID);//(线程安全属性,堆栈大小,线程函数,线程参数,线程创建属性,线程ID)
//创建属性有两种
//CREATE_SUSPENDED:创建一个挂起的线程,这个时候需要使用resumethread()函数来讲手段释放,才能执行线程
//0:表示创建后立即激活。这时候创建的线程会马上进入到任务等待队列,等待执行
ThreadCount++;
HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2);
ThreadCount++;
g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL);//(结构指针,手动或自动清除事件信号,初始状态有信号或者无信号,事件的名称)
g_hEvent2 = CreateEvent(NULL, FALSE, TRUE, NULL);
ResetEvent(g_hEvent1);
ResetEvent(g_hEvent2);
SetEvent(g_hEvent1);
while (TRUE)
{
EnterCriticalSection(&g_cs);
int nCount = ThreadCount;
LeaveCriticalSection(&g_cs);
if (nCount == 0)
{
cout << "Main break" << endl;
break;
}
}
Sleep(1000);
CloseHandle(hHandle);
CloseHandle(hHandle2);
DeleteCriticalSection(&g_cs);
cout << "Main End" << endl;
system("pause");
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
while (TRUE)
{
WaitForSingleObject(g_hEvent1, INFINITE);
cout << "线程1:" << g_dwThreadID << "thread is runing." << endl;
EnterCriticalSection(&g_cs);
int temp = g_nTickets;
LeaveCriticalSection(&g_cs);
cout << "线程:1:" << g_dwThreadID << "thread is temp." << endl;
if (temp > 0)
{
Sleep(100);
cout << "线程1:" << g_dwThreadID << "sell ticket:" << temp << endl;
EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs);
SetEvent(g_hEvent2);
}
else
{
cout << "线程1 break" << endl;
ResetEvent(g_hEvent2);//没有这个ThreadProc2不能终止
break;
}
}
EnterCriticalSection(&g_cs);
ThreadCount--;
LeaveCriticalSection(&g_cs);
cout << "线程1 end" << endl;
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
while (TRUE)
{
WaitForSingleObject(g_hEvent2, INFINITE);
cout << "线程2:" << g_dwThreadID2 << "thread is running." << endl;
EnterCriticalSection(&g_cs);
int temp = g_nTickets;
LeaveCriticalSection(&g_cs);
if (temp > 0)
{
Sleep(100);
cout << "线程2:" << g_dwThreadID2 << "sell ticket:" << temp << endl;
EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs);
SetEvent(g_hEvent1);
}
else
{
cout << "线程2 break" << endl;
ResetEvent(g_hEvent1);//没有这个ThreadProc不能终止
break;
}
}
EnterCriticalSection(&g_cs);
ThreadCount--;
LeaveCriticalSection(&g_cs);
cout << "线程2 end" << endl;
return 0;
}