linux下C++线程安全对象之互斥锁的应用

一个线程安全的class应当满足:

1)多个线程同时访问时,其表现出正确的行为。

2)无论操作系统如何调度这些线程,无论这些线程的执行顺序如何交织。

3)调用端代码无须额外的同步。

当多个控制线程共享同一个对象时,就需要确保每个线程看到一致的数据视图。这时就需要进行线程同步操作,否则就会引起竞争,linux下提供了4种方法,信号量,互斥量,条件变量,读写锁,具体如下图所示:

上面包含了Soloris和Linux对应的操作函数,一下重点介绍一下互斥量的使用。

互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁,对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会编程可运行状态,第一个变为运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等待它重新变为可用。

看一下mutex的应用

class Count : boost::noncopyable{
public:
   Count();
   ~Count();
   int getNum()const;
   int increase();
private:
   void lock();
   void unlock();
   int num;
   pthread_mutex_t mutex;
};
Count::Count():num(1){
   pthread_mutex_init(&mutex,NULL);
}
Count::~Count(){
   pthread_mutex_destroy(&mutex);
}
void Count::lock(){
   pthread_mutex_lock(&mutex);
}
void Count::unlock(){
   pthread_mutex_unlock(&mutex);
}
int Count::getNum()const{
   lock();
   return num;
}
int Count::increase(){
   lock();
   return ++num;
}

这段代码有问题,首先调用getNum()和increase()时,没有任何机会区释放所获得的锁,其次mutex的应用不符合以对象管理资源的准则。下面就使用对象管理资源。

MutexCritical.h

#include <boost/noncopyable.hpp>
#include <pthread.h>
class MutexCritical : boost::noncopyable{
public:
   MutexCritical(pthread_mutex_t _m):mutex(_m){
      pthread_mutex_lock(&mutex);
   }
   ~MutexCritical(){
      pthread_mutex_unlock(&mutex);
   }
private:
   pthread_mutex_t mutex;
};

Count.h

#include "MutexCritical.h"
class Count : boost::noncopyable{
public:
   Count();
   ~Count();
   int getNum()const;
   int increase();
private:
   int num;
   pthread_mutex_t mutex;
};

Count.cpp

#include "Count.h"
Count::Count():num(1){
   pthread_mutex_init(&mutex,NULL);
}
Count::~Count(){
   pthread_mutex_destroy(&mutex);
}
int Count::getNum()const{
   MutexCritical critiacl(mutex);
   return num;
}
int Count::increase(){
   MutexCritical critiacl(mutex);
   return ++num;
}

简易测试代码如下:

#include <iostream>
#include <stdlib.h>
#include "Count.h"
using namespace std;
void *thread(void *v);
Count count;
int main(){
   pthread_t tid1,tid2;
   int niters;
   
   pthread_create(&tid1,NULL,thread,NULL);
   pthread_join(tid1,NULL);
   pthread_create(&tid2,NULL,thread,NULL);
   pthread_join(tid2,NULL);
   exit(0);
}
void *thread(void *v){
   for(int i = 0; i< 100;++i){
       count.increase();      
       cout<<count.getNum()<<"\n";
   }
   return NULL;
}

这里虽然输出了num,但是没有显示此时的线程号,当然可以把线程号当作参数传递过来,但是更好的方法应该是将mutex和tid封装起来,将锁和线程对应起来。具体的操作可以参见陈硕的关于muduo网络库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值