创建一个线程,自然有一个对应的系统API来完毕。CreateThread这个函数就用来创建线程的。

各种參数的用途我就不多说了,这里直接贴一个我自己练习的样例

1、以下是一个创建一个线程的样例,当然,不过创建;

#include<windows.h>
#include<iostream>
using namespace std; DWORD WINAPI Fun1Pro(LPVOID laparameter);
int main()
{
HANDLE hthread1;
hthread1 = CreateThread(NULL, 0, Fun1Pro, NULL, 0, NULL);
CloseHandle(hthread1);
cout << "main thread is running \n";
return 0;
} DWORD WINAPI Fun1Pro(LPVOID Laparameter)
{
printf("The New Thread is running\n");
return 0;
}

在C++中,对于对象的引用,也是通过引用计数的方式来处理的,所以上述代码中的closehandle这个函数,仅仅是在主线程中关闭了线程的一个句柄。可是实际上创建的这个新线程还是存在的。仅仅只是这个新线程的内核对象中对这个线程的引用计数-1.否则假设不运行这种一个函数,即使这个线程运行完了。也会由于主线程中仍然有引用这个线程的痕迹从而这个线程的引用计数不为0,则不能彻底删除,仅仅有当整个进程计数的时候。才会进行清理。

执行这个程序之后能够发现,并没有看到新线程输出的那句话。

原因是这种。进程启动之后先运行了主线程,由于操作系统是通过分配给线程时间片的方式来让线程运行的,所以。在主线程的时间片内。没有特殊情况是没人打断他的,一直在运行,到了创建新的子线程的时候。由于主线程的时间片没到。所以,不可以运行子线程,之后立即又关闭了子线程的句柄,主线程运行完了,就说明整个进程也就结束了,回收了全部的资源,子线程基本上是无用的。假设要想看见子线程运行的话。那么就须要让主线程暂停运行,这时候。操作系统中的分派器就会在队列里面找到一个新的线程来运行。

让一个线程停止执行的的办法就是利用sleep()函数。使其可以暂停一下。

能够在main函数中return 0;这条语句的前面加上sleep他就 会在主线程结束之前暂停,从而运行新的子线程。

那么主线程和子线程他们直接的执行顺序究竟是什么样的呢?因为线程和进程的执行时间都是又操作系统的时间片来决定的,我对代码做了例如以下改动:

#include<windows.h>
#include<iostream>
using namespace std; DWORD WINAPI Fun1Pro(LPVOID laparameter);
int index = 0;
int main()
{
index = 0;
HANDLE hthread1;
hthread1 = CreateThread(NULL, 0, Fun1Pro, NULL, 0, NULL); CloseHandle(hthread1);
while(index++<100)
cout << "main thread is running \n";
//Sleep(10);
return 0;
} DWORD WINAPI Fun1Pro(LPVOID Laparameter)
{
while(index++<100)
printf("The New Thread is running\n");
return 0;
}

执行结果如图:

从图中我们就能够印证上面所说的了,线程的执行时间是靠时间片来决定的,当主线程的时间片执行完,可是整个主线程还没执行完的时候,操作系统的分派器也会将主线程增加线程的就绪队列。从队列中找出新的子进程来执行。

2、利用相互排斥对象实现同步:

相互排斥对象属于内核对象,他可以保证线程对单个资源拥有相互排斥的訪问权,也就是说,仅仅能由一个线程在同一时间訪问该资源。一个相互排斥对象包含:使用数量,线程ID,计数器。

ID表明如今是哪个线程拥有这个相互排斥对象。计数器用于指明该线程拥有相互排斥对象的次数。

须要调用CreateMutex函数来创建相互排斥对象。

通过WaitForSingleObject函数来请求相互排斥对象,通过ReleaseMutex函数来释放相互排斥对象。

可能看到这里大家还是不能明确为什么相互排斥对象能够实现进程间的同步作用。

首先。我们要创建一个相互排斥对象,此时这个相互排斥对象处于一个有信号状态,当我们用wait函数来请求一个相互排斥对象的时候, 那么我们此时的这个线程是可以获得相互排斥对象的訪问权,从而開始运行wait函数后面的共享代码区,同一时候,当调用一次wait的时候,相互排斥对象就从有信号变为无信号状态,由于相互排斥对象就是保证对单个资源的相互排斥訪问,假设此时还有其它的新的线程来请求相互排斥对象的訪问权从而运行共享代码的话。那么此时他得到的相互排斥对象是无信号状态,是不可以继续运行的,此时的线程会处于等待状态。当第一个线程运行完共享代码区的时候。我们要释放如今所使用的这个相互排斥对象,即用releasemutex来进行释放。他会将相互排斥对象从无信号状态设置为有信号状态,此时依据请求的先后顺序,之前在wait函数那里等待相互排斥对象信号的两个线程中的一个,就会被同意获得相互排斥的对象的訪问权,从而运行共享存储区的代码。

事实上上面的相互排斥对象和操作系统中的PV操作是同理的。

共享代码就是在wait函数和release函数中间的代码。每次仅仅能同意一个线程获得相互排斥对象的訪问权从而进入到临界区里面。wait是请求操作,release是恢复操作。

相互排斥对象另一个重要的机制,就是他包含的线程的ID.假设是线程1请求了一个相互排斥对象。那么假设线程二想用这个相互排斥对象之前,必须由线程1进行释放,在释放的过程中,相互排斥对象会拿出他维护的线程ID和释放它的线程进行比較,仅仅有两者同样的情况下才可以释放这个相互排斥对象。否则假设线程ID和释放者不一样 ,则不可以释放相互排斥对象。

CreateMutex函数中的第二个參数有两个取值,一个是false,一个是true.false代表当前的线程不拥有这个相互排斥对象,相互排斥对象处于有信号状态。true呢表示当前的线程拥有这个相互排斥对象,即当前的线程和该相互排斥对象绑定,相互排斥对象处于无信号状态。相当于默认的运行了wait函数。假设此时在这个线程里面再调用wait函数,尽管此时的相互排斥对象是无信号状态,可是由于调用他的线程和相互排斥对象内部维护的线程ID是相等的,所以依旧会获得该相互排斥对象的控制权。可是此时有一个很重要的一点,就是这个相互排斥对象的计数器+1了。一開始就说过。相互排斥对象的计数器代表了拥有这个相互排斥对象的线程拥有它的次数,所以每当调用一次wait函数的时候。计数器都会+1.所以。假设说当前线程不须要这个相互排斥对象的时候,须要调用两次释放函数,计数器才会减为0,这也就告诉了我们。释放函数的功能实际上就是让计数器-1.

3、关于相互排斥对象另一个非常重要的功能:

当一个线程里面利用wait函数请求相互排斥对象运行完成之后,在线程中并没有调用release函数来释放这个对象。所以在线程结束之后操作系统假设发现线程已经终止的话。他会自己主动帮我们释放掉这个相互排斥对象。把它变为有信号状态。

4、怎样保证仅仅有一个实例执行:

我们都知道程序仅仅是代码,一个程序执行起来能够有多个实例,那么假设仅仅让这个程序仅仅有一个实例在执行呢。

解决的方法就是利用命名的相互排斥对象来实现。原因就是。假设在调用创建相互排斥对象的函数的时候。假设之前已经有该命名的相互排斥对象存在,那么就返回已经创建的相互排斥对象,不再创建 新的,这时getlasterror将返回error_alreday_exists。

所以,假设createmutex返回的是一个有效句柄,接下来就要推断getlasterror的返回值是什么,从而断定我们 是不是在先前已经创建过了一个相互排斥对象,也就相当于已经有一个实例正在执行。

VC++学习之多线程(2)的更多相关文章

  1. 孙鑫VC学习笔记:多线程编程

    孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified ...

  2. VC++学习之VC中常见问题

    VC++学习之VC中常见问题 (1)为什么某个类突然在工作区间里面突然看不见了? 只是类隐藏了,打开FILEVIEW,找到隐藏类的头文件,随便敲一下键盘的空格键,类就会在CLASSVIEW中显示了 ( ...

  3. VC++学习之进程和线程的区别

    VC++学习之进程和线程的区别 一.进程        进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格.内存空间.磁盘 ...

  4. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  5. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  6. C#多线程学习(一) 多线程的相关概念(转)

    什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程?线程是程序中的一个执行流,每个线程都有自己的专有寄 ...

  7. VC++ 学习笔记(序):神一样的语言

    总的来说,我觉得VC++是一门神一样的语言——它是公认最强大.最复杂的:它一切以效率为第一要务,却又不肯落伍,拼命兼容现在的新的语言设计特点.本来在别的语言很容与就避开的问题,在这里要用很高的技巧去设 ...

  8. C#多线程学习(一) 多线程的相关概念

    什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程?线程是程序中的一个执行流,每个线程都有自己的专有寄 ...

  9. [转载]C#多线程学习(一) 多线程的相关概念

    原文地址:http://www.cnblogs.com/xugang/archive/2008/04/06/1138856.html 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的 ...

随机推荐

  1. 【Nodejs】理想论坛帖子爬虫1.01

    用Nodejs把Python实现过的理想论坛爬虫又实现了一遍,但是怎么判断所有回调函数都结束没有好办法,目前的spiderCount==spiderFinished判断法在多页情况下还是会提前中止. ...

  2. struts2訪问servlet的API

    1.struts作为控制器,正常非常多时候要訪问到servlet的API.经常使用功能:   (1).获取请求參数,控制界面跳转   (2).把共享数据存储于request,session,servl ...

  3. CheeseZH: Stanford University: Machine Learning Ex3: Multiclass Logistic Regression and Neural Network Prediction

    Handwritten digits recognition (0-9) Multi-class Logistic Regression 1. Vectorizing Logistic Regress ...

  4. jQuery Mobile的学习时间bottonbutton的事件学习

    程序猿都非常懒.你懂的! 生命的绝唱来机仅仅争朝夕,如诗的年华更需惜时如金. 不要让今天的懈怠成为一生的痛. 每天都在进步. 近期在学习jquery mobile开发.使用的button,绑定事件,和 ...

  5. webpack 编译ES6插件babel-loader

    1.安装babel-loader 参考:http://babeljs.io/docs/setup/#installation 进入项目目录执行安装命名: npm install --save-dev ...

  6. 剑指offer(2) - 二维数组中的查找

    题目: 在一个二维数组中.每一行都依照从左到右递增的顺序排序,每一列都依照从上往下递增的顺序排序.请写一个函数,输入一个二维数组和一个整数,推断数组中是否含有该整数. 比如以下的二维数组就是每行.每列 ...

  7. Form.ShowDialog(this)

    有时遇到一种情况,.ShowDialog()不显示.也不报错.例如以下: <span style="font-size:14px;"> private void but ...

  8. Eclipse 如何导入web项目

      Eclipse 如何导入web项目 CreateTime--2018年3月8日09:07:16 Author:Marydon 方法一:推荐使用 1.将web项目手动拷贝到Eclipse的工作空间下 ...

  9. 〖Linux〗打开qtcreater出现错误的解决方法

    1. 更换了显卡驱动,发现打开qtcreater时出现了以下的错误: qtcreator: error : cannot open shared object file: No such file o ...

  10. 基于jquery ui修改的不依赖第三方的背景透明的弹出div

    效果图: 代码: <!doctype html> <html> <head> <meta charset="utf-8"> < ...