




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、动态链接库(Dynamic Link Library, DLL)的创建、调试与加载;Windows C+的线程、信号量、互斥锁和临界区,以及Linux C+线程、互斥锁、条件变量的基本知识;设计模式:一主要学习内容 1DLL的创建、调试和调用2Windows C+线程、信号量、互斥锁、临界区3Linux C+互斥锁、条件变量、线程4观察者模式5单例模式6代理模式7适配器模式8简单工厂模式/工厂方法模式二主要收获1. DLL相关知识:动态链接库à其他应用程序共享的程序模块,封装了一些资源(数据、方法和类)。本身包含代码却不能执行,Windows应用能直接或间接调用。 静态链接:调用函数
2、或过程需要链接到.exe可执行文件中。 动态链接:DLL中的代码无需包含在.exe中,节省了宝贵的内存资源。 动态链接的优点:l 共享代码、资源和数据。l 过程隐藏l 与语言无关,增强了扩展性 (一种语言应用程序可以调用其他语言的DLL)2. DLL的创建方法VS2013新建DLL工程,选上导出符号,系统会自动生成导出DLL所需要的各种符号定义包括:#ifdef XXX_EXPORTS#define XXX_API _declspec(dllexport)#else#define XXX_API _declspec(dllimport)#endif其中XXX为你的DLL文件名 这个#idnde
3、f模块中的_declspec(dllexport)修饰的函数,告诉编译器这是DLL导出的函数,而_declspec(dllimport)告诉编译器这是从DLL导入的函数。一般,我们只使用前者就行。_declspec(dllimport)在导出静态变量时用到。为了简化,也可以采取模块定义的方式:源文件中添加.def文件(注:与DLL工程同名)Library XXXEXPORTSFunname1Funname2 DLL项目模板有导出变量、函数和类,可以根据实际情况添加自己想要实现封装的代码。此外还有stdafx.h头文件以及DLLMAIN函数,一般不做修改。编译生成后就可以得到XXX.dll和XX
4、X.lib文件。单独生成的.lib文件用于静态编译,所有信息都包含其中,不再需要.dll文件,编译时连接到应用程序会使程序过大。而和.dll文件一起生成的.lib文件则只包含了导出函数的名称和位置,具体实现都在.dll文件中,隐式加载时一起使用,动态加载时只需.dll文件。3. DLL的调用 DLL的调用分为隐式调用和显式调用两种: 隐式调用:又分为三种加载方式(需要.lib文件)l 直接将.lb文件加入到工程文件中,作为资源文件。l 通过工程设置菜单,选中Link,在其中添加.lib文件l 使用代码方式,#pragma comment(lib,”././XXX.lib”),同时需要编写DLL
5、时的头文件显示调用:只需要.dll文件,通过API完成。具体通过LoadLibraryA函数将DLL映射到进程的内存空间,实现动态加载,然后使用GetProAddress函数获取DLL中函数风地址。使用完DLL后,用FreeLibrary函数从进程空间显示卸载DLL。例:v.dll文件的创建v.cpp #include <iostream> extern "C" double multiple (double x, double y)return (x*y);extern "C" double divide(double x, double
6、y)return (double)(x/y);v.defLIBRARY vEXPORTSvmvCall.cpp#include <stdio.h>#include <Windows.h>#pragma warning(disable:4996)typedef double(*lp)(double, double);typedef void(*lr)();void main()HINSTANCE ss = LoadLibraryA("D:VS2013项目myDllDebugv.dll");if (!ss)printf("加载DLL文件出错n&
7、quot;);lp multiple = (lp)GetProcAddress(ss, " multiple ");lp divide = (lp)GetProcAddress(ss, "divide");if (!multiple | ! divide)printf("获取函数地址出错n");double x, y;scanf("%lf,%lf", &x, &y);printf("%f,%fn", x, y);printf("%fn", multiple (
8、x, y);printf("%fn", divide (x, y);FreeLibrary(ss);运行结果:8.96,5.21 8.960000,5.21000046.6816001.719770请按任意键继续. . .Tip: 使用scanf读取double类型的数据时,一定要使用%lf,并且在进行输入时,也必须按照参数列表的格式,如scanf(“%lf,%lf”,),输入必须为8.21,9.54.逗号必须匹配。 4. Windows信号量、互斥锁、临界区和线程 信号量 (Windows特有) 允许多个线程同时使用共享资源,但限定了同时访问共享资源线程的最大数目。 Cr
9、eateSemaphore(NULL,initialCount,maxCount,NULL),参数2和3指出当前可用资源 数和最大资源数。 WaitForSingleObject(XXX,time)线程访问资源,若可用资源大于0,则减1,否则阻塞 等待time时间。这个函数适用于多种对象,包括互斥锁,线程,进程等等 ReleaseSemaphore(XXX,n,& initialCount) 线程使用完资源,离开增加资源计数, initialCount增加n。 互斥锁: 共享资源同一时间只能被一个线程访问,即拥有互斥锁(只有一个)的线程。 CreateMutex() 创建一个互斥锁,第
10、二个参数的类型为BOOL,表示该互斥锁是否归 创建它的线程所拥有。 ReleaseMutex() 开锁。必须与CreateMutex()配对使用。 OpenMutex()打开一个已有的互斥锁。 WaitForSingleObject() 等待互斥锁。 临界区:(Windows特有) 任何时刻只有一个线程访问共享资源,多个线程同时访问共享资源时,后进入临界区 的线程将被挂起。临界区被释放后,后面的线程继续抢占临界区。 EnterCriticalSection()进入临界区,必须确保与LeaveCriticalSection()配对使用。 LeaveCriticalSection()释放临界区。
11、事件(Event): 通过通知操作的方式保持线程同步。 CreateEvent() 创建一个事件 OpenEvent() 打开已存在的一个事件 SetEvent() 回置事件 WaitForSingleObject() 等待一个事件 WaitForMultipleObject() 等待多个事件 它们各自的特点和区别:l 信号量是为控制一个具有有限数量的用户资源而设计l 互斥锁视为了协调同时对一个共享资源的单独访问而设计的l 临界区能将多线程串化访问公共资源或者代码。l 事件用来通知线程一些事件已发生,从而启动后续任务。l 互斥锁和临界区的作用非常相似。临界区速度快,只能用于统一进程中的不同线程
12、。互斥锁可以命名,可以通过名字打开,因而可以用于不同进程间的线程同步。l 互斥锁、信号量和事件可以用于不同进程间的数据同步。l 信号量可一个线程占用,另一个线程释放,互斥锁只能由同一线程释放。 Windows线程: 进程:系统资源分配和调度的独立单位,程序在某个数据集上的执行。 线程:进程的一个实体,CPU调度和分配的基本单位,依附于进程,不能单独执行。 进程与线程的关系: 线程属于进程,运行在进程空间。同一进程的所有线程共享内存空间。线程本身不拥 有系统资源,只有运行中必不可少的信息(程序计数器,寄存器和栈)。进程退出时, 所有线程都被强制退出并清除。 创建线程前,必须定义一个全局的线程函数
13、(线程需要做的事情) 线程函数: unsigned long _stdcall threadPro(void* ptr); DWORD WINAPI threadPro(LPVOID ptr); / 使用#define后的形式,一一对应 创建线程: Handle myThread = CreateThread(NULL,0,threadPro,NULL,0,NULL); WaitForSingleObject(myThread); 等待线程结束,在主线程中用到,不然主线程退出, 子线程也就强制退出。 CloseHandle(myTread);关闭线程句柄 适用于信号量、互斥所等等新创建的线程,
14、马上调用closehandle(线程句柄)的原因:因为新创建的线程,其线程内核对象可用计数为2,一个是线程本身,另一个是创建线程的线程,调用closehandle(线程句柄)后,可用计数减为1,新线程运行结束后,内核将使用计数减为0,然后清理线程内存资源。如果不调用closehandle(线程句柄),则在线程运行结束后,其可用计数仍为1,造成内存泄露。当然,整个程序运行完毕后,然后可以回收这些资源。 5. Linux互斥锁、条件变量和线程 互斥锁:<pthread.h>头文件 pthread_mutex_t myMutex; /声明一个互斥锁 pthread_mutex_init(
15、&myMutex); /初始化互斥锁 pthread_mutex_lock(&myMutex); /上锁 配对使用 pthread_mutex_unlock(&myMutex)/解锁 pthread_mutex_trylock(&myMutex);/尝试上锁,失败则阻塞 pthread_mutex_destroy(&myMutex);/注销互斥锁 条件变量:用于自动阻塞一个线程,直到某特殊情况发生,必须与互斥锁一起使用。 <pthread.h>头文件 pthread_cond_init someCondition /初始化一个条件变量 pth
16、read_cond_destroy(&someCondition );/摧毁条件变量 pthread_cond_wait(&someCondition, &myMutex) /条件变量等待,一直等 pthread_cond_timedwait(&someCondition, &myMutex,time) /等待time时间 Linux 线程:<process.h> Linux创建线程的函数有两种 1 线程函数:unsigned long _stdcall threadPro(void* ptr); 1 创建线程函数: void* mythre
17、ad = (void*)_beginthreadex(NULL,0,threadPro,NULL,0,NULL) 2线程函数:void _cdecl threadPro(void* ptr); 2创建线程函数: void* mythread = (void*)_beginthread(threadPro,0,NULL) Tips:l ReleaseSemaphore()的第二个参数为增加的信号量计数。l 非静态类成员函数因为带有this指针因而无法作为线程函数,可以将其声明为静态函数,同时在线程函数中将传入的this指针强制转换为该类指针。也可以将线程函数声明为友元函数。使用类对象开启启动线程
18、函数时,要注意线程执行时,对象已被析构的情况,可以使用静态对象来防止。l Sleep()函数中Sleep(0)表示放弃CPU的争夺,而不是一直占有CPU。l 使用beginthreadex创建线程更安全,因为它内部调用了CreateThread函数。CreateThread函数如果调用C运行时库,会创建ptd块,无法释放,而beginthreadex函数可以释放。 #include <process.h>#include <Windows.h> #include <iostream>using namespace std;void* Thread;class
19、 testpublic:/线程函数,静态成员函数static unsigned int _stdcall TaskTread(void* para) /将this指针强制转换为类类型指针,以便调用类成员函数test* lptr = (test*)para;lptr->dispaly();return 0;/线程函数需要调用的成员函数,非静态成员函数void dispaly() cout << "I LOVE YOU" << endl;/创建线程的成员函数,非静态成员函数void toolFun() /this指针通过强制类型转换传递给线程函数T
20、hread = (void*)_beginthreadex(NULL, 0, test:TaskTread, NULL, 0, (unsigned int*)this);test() cout << "离开作用域,执行析构." << endl; ;int main()/静态对象,防止线程函数未返回时对象t已被析构static test t; t.toolFun();WaitForSingleObject(Thread,INFINITE);CloseHandle(Thread);return EXIT_SUCCESS;6. 观察者模式 定义了对象间一对
21、多的关系,也称发布-订阅者模式。能解除对象之间的精密耦合关 系,分为观察者和被观察者,被观察者状态一旦改变,就会通知所有的观察者,它们 会更新自己的状态。观察者模式具有以下几种角色:l Subject主题或者目标,定义一个观察者集合,数量不限。提供增加和删除观察者的方法。同时声明了通知方法。l ConcreteSubject具体的主题或目标,实现通知方法l Observer观察者,对目标做出反应,基类,声明了更新方法updata()l ConcreteObserver具体观察者,维护一个指向具体目标的引用,存储了自己状态,与具体目标一致,同时实现了通知方法。 7. 单例模式 类只实例化一个对象
22、,通常将默认构造函数和复制构造函数设为私有,设定一个私有的静态对象指针,并提供一个全局的访问点。分为以下三种模式: 普通单例模式:#ifndef _SINGLETON_H_ #define _SINGLETON_H_#include <iostream>class Singletonprivate:Singleton() /将构造函数设为私有,防止外为实例化Singleton(Singleton&) /将复制构造函数声明为私有也是必要的。static Singleton* S_Instance; /一个实例class CGarbo /此类的目的是程序结束,回收单例类。pub
23、lic:CGarbo() if (S_Instance != NULL)delete S_Instance;S_Instance = NULL;static CGarbo CG;public:static Singleton* getInstance(); /提供全局访问点,同时保证只有一个实例/TO DO/.;Singleton* Singleton:S_Instance = NULL;Singleton* Singleton:getInstance()if (NULL = S_Instance) S_Instance = new Singleton();return S_Instance;
24、#endif 8. 代理模式抽象主题角色à提供真实对象和代理的共同接口。代理主题:维持真实主题的引用:操作真实对象、控制和约束其使用、创建和删除真实对象、附加操作。真实主题:代理的真实对象,实现真实(客户的)业务操作,可通过代理访问该操作。代理类型:远程代理:封装底层网络通信和对远程对象的调用。分布式技术,使远程对象更运行于计算性能与处理速度更高的远程主机。虚拟代理:适用于占用系统资源较多和加载时间较长的对象。加速系统启动。时间换空间一次创建,多次检查是否存在并利用。保护代理:对能否访问真实代理增加访问控制机制,如身份验证等等。缓冲代理:为操作结果提供临时存储空间,后续共享结果,避免
25、重复 方法的重复执行。优化系统性讷讷感智能引用代理:对访问真实代理的用户进行计数。9. 适配器模式有一个包装类(Adapter),封装了一个对象适配者(Adaptee)。客户à适配器方法à适配者类方法 (透明)实现接口转换根据关联与继承关系,包括对象适配器和类适配器。 目标类定义了一个目标接口对象适配器实现抽象目标类接口,并关联适配者类(对象适配器)即对象适配器中维护了适配者类的引用。适配者类为一个具体类,定义了已经存在的接口,目标类想要调用需要适配。(问题,一个适配器能适配多个适配者吗?)可以类适配器实现抽象接口目标类,并继承适配者类。双向适配器缺省适配器(单接口适配器模
26、式) 目标接口中有大量的方法,但并不需要全部实现,这时可以用抽象适配器类实现接口,定义需要实现的方法,不需要实现的方法提供空实现。它的子类具体适配器类就可以选择性覆盖。总结:现有接口转换为客户所需的接口,实现复用。解耦优点:接口重用,透明,扩展性和灵活性好类适配器:置换适配者方法对象适配器:适配多个适配者,适配适配者的子类(里氏代换) 10. 简单工厂模式/工厂模式 简单工厂模式: 工厂角色à负责创建所有产品实例的内部逻辑,提供静态工厂方法, 返回抽象产品类抽象产品类à所有产品的父类,封装定义他们的公有方法,声明一些具体方法(不 同的产品所需要的)。 具体产品类à
27、抽象产品类的子类,实现所有声明的方法。 通过静态工厂方法 static Product GetProduct(string arg),根据arg进行 产品的实例化: arg =”A”, return ConcreteProductA();缺点:静态工厂方法使得添加新产品必须修改源代码,不符合“开闭原则”。工厂模式:将工厂进行解耦,提供所有具体工厂的一个父类,声明一个实例化方 法,将实例化的任务交给具体工厂,实例化哪个类由它们实现。主要优点 (1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具
28、体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。 (2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。 (3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非 常好,完全符合“开闭原则”。 2. 主要缺点 工厂方法模式的主要缺点如下: (1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 龙岩廉租房申请报告(3篇)
- 防治白蚂蚁合同(标准版)
- zcs与zicisi的区别教学课件
- 公司分部门安全培训内容课件
- 2025年急救中暑试题及答案
- 创新驱动发展:2025年智能可穿戴设备睡眠监测技术在睡眠环境优化中的应用
- 临沧安全培训课件
- 品牌店转让合同(标准版)
- 付首付没给合同(标准版)
- 竞价基础试题及答案
- 某水库调度规程完整
- Cpk 计算标准模板
- 封起DE日子博文 2006
- 锂离子电池生产安全讲座
- 画魂空手套无删减全文下载
- 五猖会原文 五猖会
- 主题教育苏轼生平介绍人物经历等PPT模板(内容完整)
- 眼科学-眼科检查(课件)
- 产品碳足迹课件
- 美国地图高清中文版
- 监控中心值班人员绩效考核月度考核表
评论
0/150
提交评论