多线程c语言笔记
在c语言中使用多线程
目前项目是在windows环境下使用的MSVC来编译c语言文件
所以需要包含Windows.h头文件。如果是gcc需要包含pthread.h头文件
目前只学习了在visual studio中使用包含Windows.h头文件的方法
使用多线程需要考虑是否会多个线程同时修改共有的数据,如果有此种场景需要加入线程锁
我在c语言彩票系统主要使用下面两个函数
创建线程锁
CreatedMutex
函数
下面是创建线程锁的函数原形
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全属性
BOOL bInitialOwner, // 创建者是否初始拥有锁
LPCSTR lpName // 互斥锁名称
);
下面分别解释三个参数
第一个参数LPSECURITY_ATTRIBUTES
类型
此类型为下面安全属性的结构体指针类型
lpMutexAttributes其作用是指定互斥锁的安全描述符,控制句柄是否可继承
常用值为NULL,填入NULL则不可被子线程继承
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
第二参数BOOL
类型
bInitialOwner其作用是指定线程是否立即拥有互斥锁
FLASE
:创建后锁处于未拥有状态
TRUE
:创建者立即拥有,需要手动释放此锁,如果没有释放会使得创建了此锁的线程立刻上锁
通常用FALSE
通过WaitForSingleObject
来竞争锁
第三个参数LPCSTR
类型
此类型为指向常量字符串的指针类型
lpName其作用是为互斥锁命名,允许跨进程使用
常用值为:NULL
,创建匿名锁,仅限当前进程使用,如果为其命名“myMutex
”则可以跨进程访问
使用流程
1.创建锁
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
2.加锁
WaitForSingleObject(mutex, INFINITE); // 等待锁
3.解锁
ReleaseMutex(mutex); // 释放锁
4.清理
CloseHandle(mutex); // 关闭句柄
创建线程
CreateThread
函数
下面是创建线程函数原形
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性
SIZE_T dwStackSize, // 线程栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数地址
LPVOID lpParameter, // 传递给线程的参数
DWORD dwCreationFlags, // 创建标志
LPDWORD lpThreadId // 返回线程 ID
);
下面分别解释各个参数
1.第一个参数LPSECURITY_ATTRIBUTES
类型
其作用与上面的创建线程锁第一个参数类似,控制线程句柄是否可被继承
填入NULL
则不允许被继承,一般填NULL
即可
2.第二个SIZE_T
类型,无符号整数
其作用指定线程的栈空间大小
通常使用0为1MB大小
如果线程需要大量局部变量则设置更大值
3.第三个参数LPTHREAD_START_ROUTINE
类型
其作用指向线程执行的函数,签名必须是DWORD WINAPI ThreadFunc(LPVOID)
。
类型就是函数指针,即线程函数名
4.第四个参数lpParameter
通用指针类型,实际上就是void*
其作用是传递给线程函数的参数,可以是任意数据的地址。
常用NULL
,线程不需要参数,如果传入了数据,则需要在线程内强制转换使用
5.第五个参数DWORD
类型(32位无符号整型)
其作用是控制创建后的行为
0为线程创建后立即运行,4为线程创建后暂停,需要调用ResumeThread
来启动线程
如果想先创建线程但延迟执行则可以使用CREATE_SUSPENDED
函数
其他值没有研究还
6.第六个参数LPDWORD
类型 (其类型是指向DWORD
的一个指针)
作用是返回新线程的ID
NULL则是不需要线程ID,否则就通过指针修改其接收值
DWORD threadId;
CreatedTread(NULL, 0, threadFunc, NULL, 0, &threadId);
- 感谢你赐予我前进的力量