You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slim Reader/Writer锁死锁问题及多独占线程性能异常排查

问题分析与解决

核心问题1:共享锁的误用

线程t1使用**共享锁(Shared)**保护写操作,完全违背了SRW锁的设计原则:

  • 共享锁仅用于读操作,允许多个线程同时持有,保证读操作的并发安全;
  • 写操作必须使用独占锁(Exclusive),确保同一时间只有一个线程修改数据。

在共享锁下修改myglobalvar会直接导致数据竞争,同时引发锁等待的连锁问题:当t1长时间持有共享锁(Sleep(500))时,所有请求独占锁的线程(t2和主线程)都会被阻塞,无法执行,这就是程序变慢的直接原因。

核心问题2:SRW锁未显式初始化

虽然全局变量会被系统零初始化,且Windows的SRWLock零值是合法初始状态,但显式初始化是良好的编程习惯,可避免因环境差异导致的潜在问题。需要在main函数开头添加初始化代码。

核心问题3:锁饥饿与假死隐患

Windows的SRWLock具备写优先特性:当有线程等待独占锁时,后续的共享锁请求会被阻塞,直到独占锁被获取并释放。但你的代码中t1持有共享锁的时间长达500ms,远超过独占锁线程的执行时间,导致独占锁线程大部分时间都在等待,出现严重的写饥饿,表现为程序运行异常缓慢。极端情况下,若系统调度导致t1释放共享锁后立刻重新获取,独占锁线程可能长时间无法抢到锁,看似“死锁”(实际是饥饿导致的假死)。


修复后的代码

#include <iostream>
#include <Windows.h>

SRWLOCK mainLock;
char myglobalvar;

int main()
{
    InitializeSRWLock(&mainLock); // 显式初始化SRW锁
    myglobalvar = '0';

    HANDLE t1 = CreateThread(nullptr, 0, [](void*)->DWORD 
        {
            while (true)
            {
                // 写操作必须用独占锁
                AcquireSRWLockExclusive(&mainLock);
                myglobalvar = 'S'; 
                Sleep(500);
                ReleaseSRWLockExclusive(&mainLock);
            }
            return 0; 
        }, nullptr, 0, nullptr);

    Sleep(50);

    HANDLE t2 = CreateThread(nullptr, 0, [](void*)->DWORD
        {
            while (true)
            {
                AcquireSRWLockExclusive(&mainLock);
                myglobalvar = 'E';
                ReleaseSRWLockExclusive(&mainLock);
                Sleep(1); // 添加短暂休眠,避免过度抢占CPU
            }
            return 0;
        }, nullptr, 0, nullptr);

    for (int i = 0; i < 100; i++)
    {
        AcquireSRWLockShared(&mainLock); // 读操作使用共享锁
        std::cout << myglobalvar << '\n';
        ReleaseSRWLockShared(&mainLock);
        Sleep(50);
    }

    // 清理线程句柄,避免资源泄漏
    CloseHandle(t1);
    CloseHandle(t2);
    return 0;
}

额外优化建议

  • 严格读写分离:读操作使用共享锁,写操作使用独占锁,最大化并发效率;
  • 缩短锁持有时间:避免在锁内执行Sleep等耗时操作,将非临界逻辑移到锁外;
  • 增加退出条件:实际程序中需为无限循环线程添加终止逻辑,防止线程一直运行;
  • 资源清理:使用CloseHandle关闭线程句柄,避免系统资源泄漏。

内容的提问来源于stack exchange,提问作者Badasahog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:30:48