为什么要在编程中引入线程?
为了并行的处理多个事情或着说是为了执行多个程序,由此引出了线程。
好处:这些线程共同使用当前进程的资源(变量,文件,socket,栈.....);在这里我举一个简单地例子,利用图形库比较明显的
说明问题。
假如我们现在要在运行界面上显示随机数又要显示当前时间,可以使用多线程来完成。
HANDLE WINAPI CreateThread( //创建线程并返回线程句柄
LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程的安全属性,默认为NULL
SIZE_T dwStackSize, //线程栈的大小 0
LPTHREAD_START_ROUTINE lpStartAddress, //线程函数
drv_aliasesMem LPVOID lpParameter, //线程函数的参数
DWORD dwCreationFlags, //创建方式
LPDWORD lpThreadId //线程id
);
简单实现的代码如下:
#include "stdafx.h"
#include <graphics.h>
#include<time.h>
#include<Windows.h>
DWORD showRand(LPVOID arg) //线程的使用 执行显示随机数
{
char buff[8];
int n;
while (1)
{
n = rand() % 100000000;
sprintf(buff, "%8d", n);
outtextxy(100, 100, buff);
Sleep(100);
}
return 1;
}
DWORD showTime(LPVOID arg) //线程的使用 执行显示时间
{
//显示时间
initgraph(640, 450);
int hour, min, sec;
char buff[10];
while (1)
{
hour = time(NULL) % (3600 * 24) / 3600 + 8;
min = time(NULL) % 3600 / 60;
sec = time(NULL) % 60;
sprintf(buff, "%02d:%02d:%02d", hour, min, sec);
outtextxy(300, 200, buff);
Sleep(1000);
}
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
initgraph(640, 480); //初始化窗口
DWORD id1, id2; //创建两个线程id
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)showRand, NULL, NULL, &id1); //创建线程
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)showTime, NULL, NULL, &id2); //创建线程
while (1);
closegraph(); //关闭窗口
return 0;
}
运行界面:
(2)假如在一个程序中两个线程同时操纵一个临界数据,会导致数据脏。要避免这种情况发生,就有了线程同步的概念,
用户态的有 原子态、读写锁、临界区 内核态的有事件、互斥、信号量 内核态的开销大
简单介绍其中三种:
原子锁 :原子锁是最小的单位,不能分割
InterlockAdd(volatile LONG*)(&n,1); 在win32中封装了许多原子锁的操作
读写锁: 一般用于文档,文档正在编辑时,不能拷贝或者上传。
两把锁,一把读锁,一把写锁 读读相容,读写相斥,写写相斥
编程模型: 1.定义锁 2.初始化锁 3.操作前请求锁 4. 操作完释放锁 5.删除锁
1.SRWLOCK srwLock;
请求读锁: AcquireSRWLockShared(& srwLock)
释放读锁: ReleaseSrwLockShared(& srwLock)
请求写锁: AcquireSRWLockExclusive(& srwLock)
释放写锁:ReleaseSrwLockExclusive(& srwLock)
信号量: 本质是数字,数字减少到0之后,不能减少了,释放会增加信号量
编程模型: 1.定义信号量 2.创建信号量 3. 等待信号量 4.释放信号量
1.定义 HANDLE sem;
2.CreateSemaphore(NULL,5,100,NULL);
3.waitforsingleobject
4.ReleaseSemaphore会增加数字
写的不是很全面,等有空了在更新。