进程与线程基础

程序: 计算机指令的集合,以文件的形式存储在磁盘上

进程: 正在运行是程序实例,以是一个程序在其自身的地址空间的一次执行活动。进程有一个进程管理的内核对象和地址空间组成。

线程: 程序执行的最小单元。每个进程至少一个线程,进程是线程的容器。线程是CPU调度与运行的最小单位,而进程是资源分配的最小单位。线程由线程内核对象和线程栈组成。

Windows下线程的创建

windows下创建线程的API:

HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt __deref __drv_aliasesMem LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);

lpThreadAttributes: 线程内核对象的安全属性,传入NULL,表示使用默认安全属性。

dwStackSize: 线程栈空间大小,0表示默认大小

lpStartAddress: 新线程所执行的线程函数地址,该函数的名称随意,但必须遵照下面的声明形式:

DWORD WINAPI ThreadProc( LPVOID lpThreadParameter );

lpParameter: 传递给线程函数的参数

dwCreationFlags: 控制线程创建的附加标志,设置为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread(), 如果是0,线程创建后立即执行。

lpThreadId: 该参数是一个返回值,用来接收线程ID.

线程创建实例:

#include <Windows.h>
//线程函数
DWORD _stdcall ThreadProc (LPVOID lPparameter)
{
for (int i = 0; i < 100; ++i)
{
cout << "\n[" << i <<"] Thread1 running!";
}
return 0;
} int _tmain(int argc, _TCHAR* argv[])
{
//创建线程
HANDLE hThread;
hThread = ::CreateThread(NULL,0,&ThreadProc,NULL,0,NULL); ::WaitForSingleObject(hThread,INFINITE); //等待子线程运行结束
::CloseHandle(hThread);
cout << "\nMain thread finished!";
return 0;
}

注:上面的CloseHandle函数不是终止新创建的线程,而只是关闭线程句柄。当关闭该线程句柄时该线程的内核对象引用计数减1,当新线程执行结束后,内核对象引用计数也递减,当引用计数为0时,系统释放该线程内核对象。因此,在程序中,当不需要线程句柄时,因将它关闭。

_beginthreadex

当程序使用CRT(C运行库)时,尽量使用_beginthreadex _endthreadex来创建或结束进程。因为使用CreateThread创建进程时,如果使用了C运行库的一些函数,可能会造成一些问题。

_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread()

还有一组类似的函数,AfxBeginThread()AfxEndThread(),它是MFC层面的线程包装函数,当使用MFC类库时,尽量使用这组函数来创建线程。

线程同步

同步: 按照预定的先后次序进行运行。

多线程面临的主要问题就是同步,实现线程同步的机制一般有四种:互斥量、信号量、事件、临界区。

线程同步例子:

int g_tickets = 100;
HANDLE g_hMutex; //通过互斥对象实现同步
HANDLE g_hEvent; //通过事件对象实现线程同步
CRITICAL_SECTION g_cs; //使用临界区对象实现线程同步 unsigned int _stdcall ThreadProc1 (LPVOID lPparamter)
{
bool sell_out = false;
while (!sell_out)
{
//::WaitForSingleObject(g_hMutex,INFINITE); //请求互斥对象
//::WaitForSingleObject(g_hEvent,INFINITE); //请求事件对象
EnterCriticalSection(&g_cs); //进入临界区
if (g_tickets > 0)
{
cout << "thread1 sell ticket: " << g_tickets-- << endl;
}
else
{
sell_out = true;
}
//::ReleaseMutex(g_hMutex); //访问结束后,释放互斥对象
//::SetEvent(g_hEvent); //将事件对象置为有信号状态,允许其他等待该对象的线程可调度
::LeaveCriticalSection(&g_cs); //离开临界区
}
return 0;
} unsigned int _stdcall ThreadProc2 (LPVOID lPparamter)
{
bool sell_out = false;
while (!sell_out)
{
//::WaitForSingleObject(g_hMutex,INFINITE);
//::WaitForSingleObject(g_hEvent,INFINITE);
::EnterCriticalSection(&g_cs);
if (g_tickets > 0)
{
cout << "thread2 sell ticket: " << g_tickets-- << endl;
}
else
{
sell_out = true;
}
//::ReleaseMutex(g_hMutex);
//::SetEvent(g_hEvent);
::LeaveCriticalSection(&g_cs);
}
return 0;
} typedef unsigned int (_stdcall *pThreadProc)(LPVOID); int _tmain(int argc, _TCHAR* argv[])
{
const int THREADNUM = 2;
pThreadProc threadProcs[THREADNUM];
threadProcs[0] = &ThreadProc1;
threadProcs[1] = &ThreadProc2;
HANDLE hThreads[THREADNUM];
for (size_t threadIndex = 0; threadIndex < THREADNUM; ++threadIndex)
{
hThreads[threadIndex] = (HANDLE)::_beginthreadex(NULL,0,threadProcs[threadIndex],NULL,0,NULL);
}
//g_hMutex = ::CreateMutex(NULL,false,NULL); //使用互斥对象实现线程同步
//g_hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL);//使用自动重置事件对象实现同步
//::SetEvent(g_hEvent);
::InitializeCriticalSection(&g_cs); //使用临界区对象实现线程同步
//等待所有线程结束
::WaitForMultipleObjects(THREADNUM,hThreads,TRUE,INFINITE);
::DeleteCriticalSection(&g_cs); //释放临界区对象
cout << "\nMain thread finished!";
return 0;
}

使用互斥量、事件对象、临界区实现线程同步的总结:

互斥量和事件对象都属于内核对象,使用内核对象进行线程同步时,速度较慢。但使用内核对象可以在多个进程的各个线程间进行同步。

临界区同步方式工作在用户状态,同步速度快。故在编写多线程程序时,首选使用临界区对象进行同步。

多线程学习资料:

http://blog.csdn.net/morewindows/article/details/7392749

http://www.cnblogs.com/P_Chou/archive/2012/06/10/basic-of-thread.html

http://www.cnblogs.com/chengmin/archive/2011/09/26/2192421.html

Windows多线程基础的更多相关文章

  1. windows多线程编程星球(一)

    以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...

  2. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  3. 总结windows多线程同步互斥

    windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...

  4. windows多线程同步互斥--总结

    我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...

  5. Windows多线程编程入门

    标签(空格分隔): Windows multithread programming 多线程 并发 编程 背景知识 在开始学习多线程编程之前,先来学习下进程和线程 进程 进程是指具有一定独立功能的程序在 ...

  6. Java 多线程基础(一)基本概念

    Java 多线程基础(一)基本概念 一.并发与并行 1.并发:指两个或多个事件在同一个时间段内发生. 2.并行:指两个或多个事件在同一时刻发生(同时发生). 在操作系统中,安装了多个程序,并发指的是在 ...

  7. C++多线程基础教程

    目录 1 什么是C++多线程? 2 C++多线程基础知识 2.1 创建线程 2.2 互斥量使用 lock()与unlock(): lock_guard(): unique_lock: conditio ...

  8. Windows内核基础知识-8-监听进程、线程和模块

    Windows内核基础知识-8-监听进程.线程和模块 Windows内核有一种强大的机制,可以在重大事件发送时得到通知,比如这里的进程.线程和模块加载通知. 本次采用链表+自动快速互斥体来实现内核的主 ...

  9. Windows多线程多任务设计初步(转)

    Windows多线程多任务设计初步 [前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程 ...

随机推荐

  1. Android O 获取APK文件权限 Demo案例

    1. 通过 aapt 工具查看 APK权限 C:\Users\zh>adb pull /system/priv-app/Settings . /system/priv-app/Settings/ ...

  2. Spark学习笔记--Spark在Windows下的环境搭建

    本文主要是讲解Spark在Windows环境是如何搭建的 一.JDK的安装 1.1 下载JDK 首先需要安装JDK,并且将环境变量配置好,如果已经安装了的老司机可以忽略.JDK(全称是JavaTM P ...

  3. sencha touch tpl 实现按钮功能

    js如下: Ext.define('app.view.message.Info', { alternateClassName: 'messageInfo', extend: 'Ext.Containe ...

  4. [Offer收割]编程练习赛15 B.分数调查[加权并查集]

    #1515 : 分数调查 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的学校总共有N名学生,编号1-N.学校刚刚进行了一场全校的古诗文水平测验. 学校没有公布测 ...

  5. github的README.md文件格式

    一.在线编辑器:stackedit 网址:https://stackedit.io/ README.md是使用Markdown语法.基本规则如下: Markdown 语法速查表 1 标题与文字格式 标 ...

  6. C# 二维码 ThoughtWorks.QRCode.dll

    ThoughtWorks.QRCode.dll: 1.ThoughtWorks.QRCode.dll 2.通过 NuGet 添加 后台代码: using System; using System.Dr ...

  7. css 多行文字,超出部分隐藏,...代替

    css虽然简单,但其实也是记得常用的那些,不常用的还是要搜一搜再写

  8. FZU2110 Star【计算几何】

    Overpower often go to the playground with classmates. They play and chat on the playground. One day, ...

  9. 使用keras导入densenet模型

    从keras的keras_applications的文件夹内可以找到内置模型的源代码 Kera的应用模块Application提供了带有预训练权重的Keras模型,这些模型可以用来进行预测.特征提取和 ...

  10. HDU 2087 - 剪花布条 - [KMP算法]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...