锁和临界区有什么区别?

 一、锁和临界区差异

        他们都是实现线程同步和互斥访问共享资源的机制。从几个方面来介绍一下他们的区别;

1、定义差异

        临界区:每个进程中访问临界资源的那段代码称为临界区,临界区不是内核对象,而是系统提供的一种数据结构。程序中可以声明一个该类型的变量,之后用它来实现对资源的互斥访问。当欲访问某一临界资源时,先将该临界区加锁(若临界区不空闲则等待),用完该资源后,将临界区释放

        锁(互斥锁Mutex):锁是一种更通用的同步机制,用于保护临界区,确保同一个时刻只有一个线程可以访问共享资源;锁可以是内核对象,也可以是用户态对象,它可以在不同进程的多个线程之间同步。

2、工作模式差异

        临界区:工作在用户用户模式下,仅限与同一个进程内。

        锁:可以是内核对象,也可以在用户态进行操作。作为内核对象时,锁可以在不同进程的多个线程之间进行同步

3、性能差异

        临界区:在用户态进行锁操作,因此速度较快

        锁:作为内核对象的锁,在进行多线同步时速度较慢,因为涉及到内核态和用户态之间的切换

4、实现差异

        临界区:依赖于操作系统提供的API,如Windows中的CRITICAL_SECTION结构

        锁:锁的实现可以更加灵活,可以是简单的二元锁(如互斥锁),也可以是更复杂的锁机制,如读写锁、条件变量等

二、其它替代方法

        1、原子操作

        原子操作确保了单个操作的不可分割性,适用于简单的线程同步场景,如对共享变量的原子更新。

        C++11引入了原子操作库<atomic>,提供了一种无需使用锁的线程安全编程方式。

        2、条件变量

        条件变量用于在某些条件不满足时挂起线程,并在条件满足时被唤醒。它通常与互斥锁一起使用,以实现更复杂的同步逻辑。

        C++11中的<condition_variable>头文件提供了条件变量的支持

        3、信号量

        信号量用于控制对共享资源的访问数量。它允许多个线程在同一时刻访问同一资源,但需要限制在同一时刻访问此资源的最大线程数目。

        C++11中的<semaphore>头文件提供了信号量的支持。

        4、事件

        事件是一种同步机制,用于通知线程某个事件已经发生。它可以用来实现线程间的协调和同步。

三、使用demo

        1、临界区

#include <windows.h>
#include <iostream>

// 全局临界区对象
CRITICAL_SECTION g_cs;

// 共享资源
int sharedResource = 0;

// 线程函数,增加共享资源
void AddResource(void* param) {
    EnterCriticalSection(&g_cs); // 进入临界区

    std::cout << "Adding to resource..." << std::endl;
    sharedResource += 1; // 修改共享资源
    std::cout << "Resource value: " << sharedResource << std::endl;

    LeaveCriticalSection(&g_cs); // 离开临界区
}

// 线程函数,读取共享资源
void ReadResource(void* param) {
    EnterCriticalSection(&g_cs); // 进入临界区

    std::cout << "Reading resource..." << std::endl;
    std::cout << "Resource value: " << sharedResource << std::endl;

    LeaveCriticalSection(&g_cs); // 离开临界区
}

int main() {
    // 初始化临界区
    InitializeCriticalSection(&g_cs);

    // 创建两个线程,一个增加资源,一个读取资源
    HANDLE hThreadAdd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AddResource, NULL, 0, NULL);
    HANDLE hThreadRead = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadResource, NULL, 0, NULL);

    // 等待线程结束
    WaitForSingleObject(hThreadAdd, INFINITE);
    WaitForSingleObject(hThreadRead, INFINITE);

    // 清理临界区
    DeleteCriticalSection(&g_cs);

    // 关闭线程句柄
    CloseHandle(hThreadAdd);
    CloseHandle(hThreadRead);

    return 0;
}

2、锁

// std::mutex
// std::lock_guard
// std::unique_lock,
std::mutex tx;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值