多线程的那点儿事(之嵌套锁)

本文深入探讨了嵌套锁的概念及其在编程中遇到的挑战,详细介绍了嵌套锁的数据结构、申请与释放机制,并指出其作为统计锁而非新锁类型的特点。通过实例演示了如何使用嵌套锁解决公共函数间互斥访问的问题,强调了其在不同开发者协作场景下的实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

    嵌套锁这个概念,主要是为了根据编程中的一种情形引申出来的。什么情况呢,我们可以具体说明一下。假设你在处理一个公共函数的时候,因为中间涉及公共数据,所以你加了一个锁。但是,有一点比较悲哀。这个公共函数自身也加了一个锁,而且和你加的锁是一样的。所以,除非你的使用的是信号量,要不然你的程序一辈子也获取不了这个锁。

  1. HANDLE hLock; 
  2.  
  3. void sub_func() 
  4.     /*...*/ 
  5.     WaitForSingleObject(hLock, INFINITE); 
  6.     do_something(); 
  7.     ReleaseMutex(hLock); 
  8.     /*...*/ 
  9.  
  10. void data_process() 
  11.     /*...*/     
  12.     WaitForSingleObject(hLock, INFINITE); 
  13.     sub_func(); 
  14.     ReleaseMutex(hLock); 
  15.     /*...*/ 
HANDLE hLock;

void sub_func()
{
    /*...*/
    WaitForSingleObject(hLock, INFINITE);
    do_something();
    ReleaseMutex(hLock);
    /*...*/
}

void data_process()
{
    /*...*/    
    WaitForSingleObject(hLock, INFINITE);
    sub_func();
    ReleaseMutex(hLock);
    /*...*/
}
    出现这种情况的原因很多。很重要的一个方面是因为软件的各个模块是不同的人负责的。所以本质上说,我们根本无法确定别人使用了什么样的锁。你也无权不让别人使用某个锁。所以,遇到这种情况,只好靠你自己了。嵌套锁就是不错的一个解决办法。


    (1)嵌套锁的数据结构

  1. typedef struct _NestLock 
  2.     int threadId; 
  3.     int count; 
  4.     HANDLE hLock; 
  5. }NestLock; 
  6.  
  7. NestLock* create_nest_lock(HANLDE hLock) 
  8.     NestLock* hNestLock = (NestLock*)malloc(sizeof(NestLock)); 
  9.     assert(NULL != hNestLock); 
  10.  
  11.     hNestLock->threadId = hNestLock->count = 0; 
  12.     hNestLock->hLock = hLock; 
  13.     return hNestLock; 
typedef struct _NestLock
{
    int threadId;
    int count;
    HANDLE hLock;
}NestLock;

NestLock* create_nest_lock(HANLDE hLock)
{
    NestLock* hNestLock = (NestLock*)malloc(sizeof(NestLock));
    assert(NULL != hNestLock);

    hNestLock->threadId = hNestLock->count = 0;
    hNestLock->hLock = hLock;
    return hNestLock;
}

    (2)申请嵌套锁

  1. void get_nest_lock(NestLock* hNestLock) 
  2.     assert(NULL != hNestLock); 
  3.  
  4.     if(hNestLock->threadId == GetThreadId()) 
  5.     { 
  6.         hNestLock->count ++; 
  7.     }else
  8.         WaitForSingleObject(hNestLock->hLock); 
  9.         hNestLock->count = 1; 
  10.         hNestLock->threadId = GetThreadId(); 
  11.     } 
void get_nest_lock(NestLock* hNestLock)
{
    assert(NULL != hNestLock);

    if(hNestLock->threadId == GetThreadId())
    {
        hNestLock->count ++;
    }else{
        WaitForSingleObject(hNestLock->hLock);
        hNestLock->count = 1;
        hNestLock->threadId = GetThreadId();
    }
}

    (3)释放锁

  1. void release_nest_lock(NestLock* hNestLock) 
  2.     assert(NULL != hNestLock); 
  3.     assert(GetThreadId() == hNestLock->threadId); 
  4.  
  5.     hNestLock->count --; 
  6.     if(0 == hNestLock->count){ 
  7.         hNestLock->threadId = 0; 
  8.         ReleaseMutex(hNestLock->hLock); 
  9.     } 
void release_nest_lock(NestLock* hNestLock)
{
    assert(NULL != hNestLock);
    assert(GetThreadId() == hNestLock->threadId);

    hNestLock->count --;
    if(0 == hNestLock->count){
        hNestLock->threadId = 0;
        ReleaseMutex(hNestLock->hLock);
    }
}

文章总结:
    (1)嵌套锁与其说是新的锁类型,不如说是统计锁而已
    (2)嵌套锁和普通的锁一样,使用十分方便
    (3)嵌套锁也有缺点,它给我们的锁检测带来了麻烦
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值