编城浪子的博客
游戏开发、图形引擎

最近一段时期准备温习多线程同步相关内容,主要包括关键代码段和各种内核同步对象。先学习最简单的同步方法--Critical Section。所谓关键代码段,是指给一段代码加上锁,要执行这段代码,必须拿到一把钥匙,而且这把钥匙世界上仅存一把,独一无二。

如下代码所示:

CRITICAL_SECTION g_cs;

EnterCriticalSection(&g_cs);

//add your critical code here

....

LeaveCriticalSection(&g_cs);

在执行...这段代码前,必须确保g_cs没有被其他线程占有,否则线程就在此处挂起。通过这种方式可以保护某个资源,不被多个线程同时访问。

以下代码演示了两个线程在使用Critical Section和不使用的条件下的输出结果:

// stdafx.h : 标准系统包含文件的包含文件,

// 或是经常使用但不常更改的

// 特定于项目的包含文件

#pragma once

#define WIN32_LEAN_AND_MEAN                                       // Windows 头中排除极少使用的资料

#include <stdio.h>

#include <tchar.h>

#include <iostream>

 

// critical_section.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include <Windows.h>

 

using namespace std;

 

CRITICAL_SECTION g_cs;

int g_var = 0;

 

DWORD WINAPI ThreadProc(LPVOID lpParam)

{

                    cout << "child thread started!\n";

                    for(int i=0;i<30;i++)

                    {

                                         //EnterCriticalSection(&g_cs);

                                         cout << "The " << "child ";

                                         cout << "thread " << "enter ";

                                         cout << "the CS!" << "\n";

                                         g_var++;

                                         cout << "g_var added by 1: g_var = " << g_var << endl;

                                         cout << "The " << "child " << "thread " << "leave " << "the CS!" << "\n";

                                         //LeaveCriticalSection(&g_cs);

                    }

                    cout << "child thread ended!\n";

                    return 0;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

                    cout << "main thread started!\n";

                    InitializeCriticalSection(&g_cs);

                    DWORD tid;

 

                    HANDLE hThread = CreateThread(0, 0, ThreadProc, 0, 0, &tid);

 

                    for(int i=0;i<30;i++)

                    {

                                         //EnterCriticalSection(&g_cs);

                                         cout << "The " << "main " << "thread ";

                                         cout << "enter " << "the CS!" << "\n";

                                         g_var--;

                                         cout << "g_var minused by 1: g_var = " << g_var << endl;

                                         cout << "The " << "main " << "thread ";

                                         cout << "enter " << "the CS! " << "\n";

                                         //LeaveCriticalSection(&g_cs);

                    }

 

                    WaitForSingleObject(hThread, INFINITE);

 

                    CloseHandle(hThread);

 

                    DeleteCriticalSection(&g_cs);

 

                    cout << "main thread ended!\n";

                    return 0;

}

将如下代码的注释去掉即变成了使用Critical Section的实例。

//EnterCriticalSection(&g_cs);

//LeaveCriticalSection(&g_cs);

EnterCriticalSection()的缺点是如果g_cs仍未被其他线程释放,就一直在此处挂起,如果不想线程挂起,可以用替代函数:

BOOL WINAPI TryEnterCriticalSection(

  __inout  LPCRITICAL_SECTION lpCriticalSection

);

下一章将讲述互斥--Mutex的使用。

posted on 2008-10-30 23:10 zengfancy 阅读(504) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理