std::mutex和CRITICAL_SECTION性能比较

测试代码:

#include "stdafx.h"
#include <Windows.h>
#include <mutex>
#include <thread>
#include <vector>
#include <chrono>
#include <iostream>

const int tastCount = 160000;
int numThreads;
const int MAX_THREADS = 16;

double g_shmem = 8;
std::mutex g_mutex;
CRITICAL_SECTION g_critSec;

void sharedFunc(int i, double &data)
{
    for (int j = 0; j < 100; j++)
    {
        if (j % 2 == 0)
            data = sqrt(data);
        else
            data *= data;
    }
}

void threadFuncCritSec() {
    double lMem = 8;
    int iterations = tastCount / numThreads;
    for (int i = 0; i < iterations; ++i) {
        for (int j = 0; j < 100; j++)
            sharedFunc(j, lMem);
        EnterCriticalSection(&g_critSec);
        sharedFunc(i, g_shmem);
        LeaveCriticalSection(&g_critSec);
    }
    printf("results: %f\n", lMem);
}

void threadFuncMutex() {
    double lMem = 8;
    int iterations = tastCount / numThreads;
    for (int i = 0; i < iterations; ++i) {
        for (int j = 0; j < 100; j++)
            sharedFunc(j, lMem);
        g_mutex.lock();
        sharedFunc(i, g_shmem);
        g_mutex.unlock();
    }
    printf("results: %f\n", lMem);
}

void testRound()
{
    std::vector<std::thread> threads;

    auto startMutex = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < numThreads; ++i)
        threads.push_back(std::thread(threadFuncMutex));
    for (std::thread& thd : threads)
        thd.join();
    auto endMutex = std::chrono::high_resolution_clock::now();

    std::cout << "std::mutex:       ";
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(endMutex - startMutex).count();
    std::cout << "ms \n\r";

    threads.clear();
    auto startCritSec = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < numThreads; ++i)
        threads.push_back(std::thread(threadFuncCritSec));
    for (std::thread& thd : threads)
        thd.join();
    auto endCritSec = std::chrono::high_resolution_clock::now();

    std::cout << "CRITICAL_SECTION: ";
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(endCritSec - startCritSec).count();
    std::cout << "ms \n\r";
}

int _tmain(int argc, _TCHAR* argv[]) {
    InitializeCriticalSection(&g_critSec);

    std::cout << "Tasks: " << tastCount << "\n\r";

    for (numThreads = 1; numThreads <= MAX_THREADS; numThreads = numThreads * 2) {
        if (numThreads == 16)
            numThreads = 12;
        Sleep(100);
        std::cout << "Thread count: " << numThreads << "\n\r";
        testRound();
    }

    DeleteCriticalSection(&g_critSec);
    return 0;
}

 

测试环境VS2013

测试结果:

Tasks: 160000
Thread count: 1
std::mutex:       12096ms
CRITICAL_SECTION: 12060ms
Thread count: 2
std::mutex:       5206ms
CRITICAL_SECTION: 5110ms
Thread count: 4
std::mutex:       2643ms
CRITICAL_SECTION: 2625ms
Thread count: 8
std::mutex:       1632ms
CRITICAL_SECTION: 1702ms
Thread count: 12
std::mutex:       1227ms
CRITICAL_SECTION: 1244ms

 

### 解决 `std::unique_lock<std::shared_mutex>` 双重解锁问题 双重解锁通常发生在同一个锁对象被多次释放的情况下,这可能导致未定义行为。为了防止这种情况发生,在使用 `std::unique_lock` `std::shared_mutex` 时应遵循一些最佳实践。 #### 使用所有权标志控制锁定状态 通过设置 `_M_owns` 成员变量来管理锁的状态是一个内部实现细节,不应直接操作此成员。相反,应该利用 `std::unique_lock` 提供的方法来安全地管理锁: - 构造函数中的第二个参数可以选择延迟加锁 (`std::defer_lock`) 或者尝试立即加锁。 - 明确调用 `lock()` 方法获取独占访问权限。 - 调用 `unlock()` 手动释放锁之前要确认当前确实持有该锁。 ```cpp #include <iostream> #include <thread> #include <chrono> #include <shared_mutex> void safe_double_unlock(std::shared_mutex& sm) { std::unique_lock<std::shared_mutex> ul(sm, std::defer_lock); try { if (ul.try_lock()) { // 尝试获得锁 // Critical section... bool ownsLock = ul.owns_lock(); // 检查是否拥有锁 if (ownsLock && !ul.mutex()->try_lock_shared()) { ul.unlock(); } } else { std::cout << "Failed to acquire lock." << std::endl; } } catch (...) { // Handle exceptions here. } } ``` 当需要确保不会意外地两次解除同一把锁时,可以在解空前再次验证是否仍然持有着它,并且还可以考虑其他线程可能已经获得了共享模式下的读取锁[^1]。 此外,对于更复杂的场景,建议采用 RAII(Resource Acquisition Is Initialization)原则设计类封装资源管理生命周期逻辑,从而减少手动干预带来的风险[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值