《VC++深入详解–学习笔记》(15)多线程

Filed Under (VC++ 学习笔记) by panmaoru on 20-12-2009

本章主要介绍多线程程序的编写,并利用多线程技术创建一个网络聊天室。

15.1基本概念

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

进程被定义为一个正在运行的程序的实例,是一个程序在其自身的地址空间中的一次执行活动。

进程的组成:操作系统用来管理进程的内核对象和地址空间。进程不执行任何东西,它只是程序的实例,线程的容器或执行环境。创建一个进程之后,操作系统会自动为这个进程创建一个主线程(执行main或者winmain函数的线程)。

线程是进程中的一个实体,是被系统独立调度和分派的基本单位。

线程的组成:线程的内核对象(操作系统用来存放线程统计信息)和线程栈(维护线程在执行代码时候所需要的所有的函数和局部变量)。一个线程之后一个内核对象和一个栈。

15.2线程创建函数

可使用系统提供的API函数CreateThread来创建一个线程。

该函数的原形如下:

HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD

  DWORD dwStackSize,                        // initial stack size

  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function

  LPVOID lpParameter,                       // thread argument

  DWORD dwCreationFlags,                    // creation option

  LPDWORD lpThreadId                        // thread identifier

);

根据CreateThread函数的参数说明,可以基本了解创建一个线程的规则。

15.3简单的多线程示例

#include <windows.h>

#include <iostream.h>

DWORD WINAPI Function1(LPVOID lpParamete);//申明过程函数

void main()

{

       HANDLE hThreadl;

       hThreadl=CreateThread(NULL,0,Function1,NULL,0,NULL);

       CloseHandle(hThreadl);

       cout<<"main thread is running"<<endl;

       Sleep(10);//主线程执行完毕后,休眠10毫秒,启动子线程

}

DWORD WINAPI Function1(LPVOID lpParamete)

{

       cout<<"thread1 is running"<<endl;

       return 0;

}

在创建一个线程的时候需要指定过程函数,因此需要在main函数之前申明Function1,也可以将Function1函数的实现放到main函数之前,这样就不需要声明了。

15.4线程同步

操作系统为每一个运行线程安排一定的CPU时间—时间片。在一个多线程的程序中,系统通过一种循环的方式为线程提供时间片,线程在自己的时间片內运行。这就可以会出现一种情况:当多个线性同时对一个全局的对象进行访问时,一个线程已经进入了循环体,这时候时间片结束,该线程进入睡眠状态,系统转向执行另外一个线程。而当另外一个线程执行的时候对全局变量做了修改。当返回到第一个线程的时候,接着从上次时间片结束的地方执行,这时候会出现一些异常。

DWORD WINAPI Function1(LPVOID lpParamete)

{

       while(true) {

              if(count>0) {

                     //当线程执行到此的时候,时间片到了,线程1Sleep,开始执行线程2,当线性2完毕之后再回到线程1,接着从此处执行。这时候有可能线程count的值已经为非正常值,如:0。

                     cout<<"thread1 sell the ticket:"<<count--<<endl;

              }

              else

                     break;

       }

       return 0;

}

DWORD WINAPI Function2(LPVOID lpParamete)

{

       while(true) {

              if(count>0)

              {cout<<"thread2 sell the ticket:"<<count--<<endl; }

              else

                     break;

       }

       return 0;

}

15.4.1互斥对象实现线程同步

互斥对象mutex属于内核对象,它能够确保线程对当资源的互斥访问权。创建互斥对象的CreateMutex函数的声明如下:

HANDLE CreateMutex(

  LPSECURITY_ATTRIBUTES lpMutexAttributes,  // 互斥对象安全性,默认NULL

  BOOL bInitialOwner,                       // 指定互斥对象的拥有者,默认FALSE

  LPCTSTR lpName                            // 指定互斥对象的名称,默认NULL

);


一个线程需要申请才能获取对一个互斥对象的所有权,等使用结束之后,需要释放对该对象的所有权。申请和释放的函数申明如下:

DWORD WaitForSingleObject(

  HANDLE hHandle,        // 互斥对象句柄

  DWORD dwMilliseconds   //等待时间,默认INFINITE

);

BOOL ReleaseMutex(

  HANDLE hMutex   //互斥对象句柄

);

使用互斥对象的原则是谁拥有谁释放。使用互斥对象实现的火车售票程序的代码如下:

#include <windows.h>

#include <iostream.h>

DWORD WINAPI Function1(LPVOID lpParamete);

DWORD WINAPI Function2(LPVOID lpParamete);

int count=100;

HANDLE hMutex;

void main()

{

       hMutex=CreateMutex(NULL,TRUE,NULL);//此处第二个参数设置为真相当于把互斥对象授权给主线程,因此需要在主线程中释放

       HANDLE hThreadl;

       hThreadl=CreateThread(NULL,0,Function1,NULL,0,NULL);

       CloseHandle(hThreadl);

       HANDLE hThread2;

       hThread2=CreateThread(NULL,0,Function2,NULL,0,NULL);

       CloseHandle(hThread2);

       ReleaseMutex(hMutex);//释放,谁拥有谁释放

       Sleep(4000);

      

}

DWORD WINAPI Function1(LPVOID lpParamete)

{

       while(true)

       {

              WaitForSingleObject(hMutex,INFINITE);

              if(count>0)

              {

                     //Sleep(1);

                     cout<<"thread1 sell the ticket:"<<count--<<endl;

              }

              else

                     break;

              ReleaseMutex(hMutex);

       }

       return 0;

}

DWORD WINAPI Function2(LPVOID lpParamete)

{

       while(true)

       {

              WaitForSingleObject(hMutex,INFINITE);

              if(count>0)

              {

                     //Sleep(1);

                     cout<<"thread2 sell the ticket:"<<count--<<endl;

              }

              else

                     break;

              ReleaseMutex(hMutex);

       }

       return 0;

}

15.5网络聊天室的实现

代码就不贴上来了。

Comments (1)

  1. 多线程俺至今还没弄明白到底是咋回事,互斥对象,关键代码段用的稀里糊涂

Post a comment