C++多线程同步技巧(一) --- 临界区

简介

C++中关于多线程的内容对于构建工程来说是至关重要的,C++本身也对关于多线程的操作提供了很好的支持。本章笔者就来介绍一下C++有关于多线程的重要知识点---临界区

临界区的作用

线程就像是进程的影子,可以帮助进程几乎在同一个时间内执行更多的任务。但是由于线程不占有资源,所有的线程共享进程的资源,这样就导致多个线程在共享进程资源的时候会出现抢夺资源的情况,这些会被抢夺的资源就被称为是临界资源,例如打印机资源文件读写,如果出现线程抢占,就会导致输出混乱。所以我们在进行对临界资源访问的时候,我们应该先将要进行的操作进入临界区,然后在操作完成后退出临界区,并最后删除临界区。

C++代码样例


/*
*@Author: PeterZ
*@Time: 2018/2/14 0:06
*@Function: 线程模拟写文件,执行完成后输出完成提示语句
*/

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <Windows.h>

using namespace std;

#define THREADNUM 5                                                 //定义线程数
#define WRITENUM 100                                                //定义文件写入数量

typedef struct ThreadWorkParam {                                    //构造传参结构体
    int i;
    HANDLE hFile;
}Twp;

CRITICAL_SECTION g_cs;

DWORD WINAPI ThreadWork(LPVOID lpParam)
{
    Twp* p = (Twp*)lpParam;                                                  //传递结构体参数
    DWORD dwWrite;                                                          //文件真实写入字节数
    const char *Data = "========>HelloWorld<=========\r\n";
    for (int i = 0; i < WRITENUM; i++)
    {
        EnterCriticalSection(&g_cs);                                         //进入临界区
        WriteFile(p->hFile, Data, strlen(Data), &dwWrite, NULL); //写入文件
        LeaveCriticalSection(&g_cs);                                         //退出临界区
    }
    printf("NO.%d Process Run Over !\n", p->i);
    return 0;
}

int main(void)
{
    HANDLE hFile = CreateFile("demo.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)              //文件创建失败
    {
        printf("CREATE FILE ERROR >_<...");
    }
    DWORD dwThreadId;                                           //线程统一ID
    HANDLE hThread[THREADNUM];
    Twp TWparam;                                                     //实例化待传参结构体
    TWparam.hFile = hFile;
    InitializeCriticalSection(&g_cs);                         //初始化临界区
    for (int i = 0; i < THREADNUM; i++)
    {
        TWparam.i = i + 1;
        hThread[i] = CreateThread(NULL, NULL, ThreadWork, LPVOID(&TWparam), 0, &dwThreadId);        //创建线程
    }
    WaitForMultipleObjects(5, hThread, true, INFINITE);                      //等待线程运行结束
    DeleteCriticalSection(&g_cs);                                                               //删除临界区
    CloseHandle(hFile);
    system("pause");
    return 0;
}

原文地址:https://www.cnblogs.com/PeterZ1997/p/9735269.html

时间: 2024-10-09 10:12:51

C++多线程同步技巧(一) --- 临界区的相关文章

多线程(四)多线程同步_Critical Section临界区

临界区是指一个小代码段,在代码能够执行前,它必须独占对某些共享资源的访问权.和使用mutex一样,它们都是以原子操作方式来对共享资源进行访问. 临界区又叫关键代码段,与上一篇的mutex互斥体实现的功能一样,都是为了让多线程同步 从上面图片可以看到二者的区别,如果是在当前进程进行线程同步,只需要采用临界区即可 如果需要跨进程,就采用互斥体,最常用的一种情况就是通过在程序初始化时先打开斥体对象,如果失败就创建一个互斥体对象,反之就结束进程,以此来保证程序在任意时间只运行一份 临界区中所有API都需

C++多线程同步技巧(二)--- 事件

简介 Windows在线程同步方面提供了多种信号处理机制,其中一种便是使用 CreateEvent() 函数创建事件,然后使用信号控制同步.其中将事件变为有信号可使用 SetEvent() 函数,将事件信号复位(变为无信号)可使用 ResetEvent() 函数,信号可以配合 WaitForSingleObject() 函数进行控制,当有信号时,此函数便会放行:无信号时,此函数会将阻塞. 提示: CreateEvent() 函数的参数 bManualReset 的含义是信号是否由人工复位,如果选

C++多线程同步技巧(三)--- 互斥体

简介 Windows互斥对象机制. 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问,在线程同步与保证程序单体运行上都有相当大的用处. 代码样例 //////////////////////////////// // // FileName : MutexDemo.cpp // Creator : PeterZheng // Date : 2018/10/23 21:27 // Comment : The usage of "Creat

Delphi多线程编程(8)--多线程同步之CriticalSection(临界区)

转载自:万一的博客 先看一段程序 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1=class(TForm) ListBox1: TListBox; Button1: TButton; procedure FormCreate(Sender: TObject); procedure

多线程同步程序的测试思路

这里我有一个简单的思路,来源于去年应届生找工作做大量的名企笔试题里他人的技巧. 多线程的测试使用cout是不靠谱的,因为多个线程使用cout很容易产生混乱的输出,而且耗时. 多线程的测试往往需要知道多个线程同时运行的时候对某个共享区域的使用是否正确,为了检验正确性,比较好的测试用例就是:递增的整数序列 递增的整数序列中的每一个整数都对应一个线程的动作,最后我们将这些整数再当成另一个标记数组的下标,下标对应的值就是我们操作的动作执行的次数 只要用于标记的数组每一个元素都是1,即可. 比如: (1)

嵌入式 Linux进程间通信(十二)——多线程同步

嵌入式 Linux进程间通信(十二)--多线程同步 多线程编程中有三种线程同步机制:互斥锁.信号量.条件量.本文将使用生产者消费者问题编程实践三种线程同步方式. 生产者.消费者问题:生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费.消费者线程从缓冲区中获得物品,然后释放缓冲区.当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区.当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来. 一.互斥锁

[一个经典的多线程同步问题]总结

针对一个经典的线程同步互斥问题,前面几篇文章提出了四种解决方案:关键段.事件.互斥量.信号量. 下面对这四种解决方案做一个总结,梳理一下知识点: 首先来看下关于线程同步互斥的概念性的知识,相信大家通过前面的文章,已经对线程同步互斥有一定的认识了,也能模糊的说出线程同步互斥的各种概念性知识,下面再列出从<计算机操作系统>一书中选取的一些关于线程同步互斥的描述.相信先有个初步而模糊的印象再看下权威的定义,应该会记忆的特别深刻. 1.线程(进程)同步的主要任务 答:在引入多线程后,由于线程执行的异步

多线程同步_Monitor

多线程一直在学习和理解中...... Monitor类是多线程中用以实现同步的一种技术,主要是同一进程内多线程间的同步技术. Monitor类中有以下几个方法需要注意: Monitor.Enter(object obj)方法,其意义相当于Lock(obj): Monitor.Exit(object obj)方法,意思是释放被锁的对象 Monitor.Wait(object obj)方法,释放被锁的对象,并阻塞当前线程,等待其他线程通知(Pulse)再次获得锁 (个人理解 当前线程释放锁 自己也阻

Qt 多线程同步 与 通信

转自网络 1 多线程同步 Qt提供了以下几个类来完成这一点:QMutex.QMutexLocker.QSemphore.QWaitCondition. 当然可能还包含QReadWriteLocker.QReadLocker.QWriteLocker,但线程同步是应用很少,这里只做简单的讲解! QMutex.QMutexLocker QMutex类提供了一个保护一段临界区代码的方法,他每次只允许一个线程访问这段临界区代码.QMutex::lock()函数用来锁住互斥量,如果互斥量处于解锁状态,当前