C/C++处理多个mutex

C/C++ 处理多个 mutex

C语言

已知在一个多线程的环境,有一个结构体用于计数。

struct counter
{
    pthread_mutex_t    m;
    int                cnt;
} counter_t;

其中 m 是互斥锁,用于保证数据 cnt 的排他性访问。


当我们需要交换同一个结构体的两个对象时,很容易就会写出下面的代码。

void counter_swap( counter_t *a, counter *b )
{
    int tmp;
    
    pthread_mutex_lock( a->m );        /* 上锁 */
    pthread_mutex_lock( b->m );
    
    tmp = a->cnt;
    a->cnt = b->cnt;
    b->cnt = tmp;
    
    pthread_mutex_unlock( b->m );     /* 解锁 */
    pthread_mutex_unlock( a->m );
}

如果一条线程执行 counter_swap( x, y ) 的同时,另一条执行 counter_swap( y, x ) 就会发生死锁


为了避免死锁,该函数需要如下修改:

void counter_swap( counter_t *a, counter *b )
{
    int tmp;
    
    if( a == b ) {
        return;
    }
    else if( a < b ) {
        pthread_mutex_lock( a->m );        /* 先锁低地址 */
        pthread_mutex_lock( b->m );
        
        tmp = a->cnt;
        a->cnt = b->cnt;
        b->cnt = tmp;
        
        pthread_mutex_unlock( b->m );
        pthread_mutex_unlock( a->m );
    }
    else {
        pthread_mutex_lock( b->m );        /* 先锁低地址 */
        pthread_mutex_lock( a->m );
        
        tmp = a->cnt;
        a->cnt = b->cnt;
        b->cnt = tmp;
        
        pthread_mutex_unlock( a->m );
        pthread_mutex_unlock( b->m );
    }
}

一个函数如果要锁住相同类型的多个对象,为了保证始终按相同的顺序加锁,我们可以比较mutex对象的地址,始终先加锁地址比较小的mutex


C++

C++ 相比 C 就方便很多:

  • C++ 有 RAII 机制的 guard,锁上后可以自动解锁
  • C++ 的 std::lock() 函数确保了对多个mutex上锁而不死锁
  • C++ 有std::swap() 函数,无需自己交换
class counter
{
public:
    std::mutex   m;
    int          cnt;
};

void counter_swap( counter &a, counter &b )
{
    std::lock( a.m, b.m );
    std::lock_guard<std::mutex> guard1( a.m, std::adopt_lock );
    std::lock_guard<std::mutex> guard2( b.m, std::adopt_lock );
    std::swap<int>( a.cnt, b.cnt );
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值