zoukankan      html  css  js  c++  java
  • c++ 封装线程库 0

    1.互斥锁简介

    互斥锁主要用于互斥,互斥是一种竞争关系,用来保护临界资源一次只被一个线程访问。 
    POSIX Pthread提供下面函数用来操作互斥锁。

    int pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutexattr_t *mutexattr);
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    //返回:
    //pthread_mutex_init总是返回0
    //其他mutex函数返回0表示成功,非0的错误码表示失败
    #define CHECK(exp) 
        if(!exp) 
        { 
            fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.
    ",__FILE__, __LINE__); abort();
        }
    

     由于pthread系列函数返回成功的时候都是0,因此,我们可以写一个宏作为一个轻量级的检查手段,来判断处理错误。

    实际使用的时候只需:     CHECK(!pthread_mutex_lock(&mutex));

    2.互斥锁的封装

    需要考虑以下几个问题:

    a.互斥锁的初始化与销毁。 
    b.互斥锁的操作:加锁和释放锁。

    另外,我们的自己封装的类不应该有赋值和拷贝构造的语义,这一点跟单例模式类似,我们可以使我们的类继承自boost库的noncopyable。

    //MutexLock.h
    
    #ifndef __MUTEXLOCK_H__
    #define __MUTEXLOCK_H__
    #include <iostream>
    #include <cstdio>
    #include <boost/noncopyable.hpp>
    #include <pthread.h>
    #include <assert.h>
    
    #define CHECK(exp) 
        if(!exp) 
    { 
        fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.
    ",__FILE__, __LINE__); abort();
    }
    
    class MutexLock : public boost::noncopyable
    {
        friend class Condition;//条件变量友元声明
        public:
            MutexLock();
            ~MutexLock();
            void lock();
            void unlock();
            bool isLocking() const 
            {
                return isLocking_;
            }
            pthread_mutex_t *getMutexPtr()
            {
                return &mutex_;
            }
        private:
            void restoreMutexStatus()
            {
                isLocking_=true;
            }
            pthread_mutex_t mutex_;//互斥锁
            bool isLocking_;
    };
    #endif
    

      这里完成了MutexLock 类的声明,但是这里还需要一些补充,那就是使用RAII(资源获取即初始化)技术,对MutexLock初始化和析构进行处理:初始化的时候加锁,析构的时候解锁,这就需要我们重新定义一个class MutexLockGuardMutexLock进行操作

    class MutexLockGuard:public boost::noncopyable
    {
        public:
            MutexLockGuard(MutexLock &mutex):mutex_(mutex){ mutex_.lock();}//构造时加锁
            ~MutexLockGuard()//析构时解锁
            {
                mutex_.unlock();
            }
        private:
            MutexLock &mutex_;//注意这里为什么是引用!!!!
    };

    下面就要具体实现几个函数了,主要是: 
    pthread_mutex_init()pthread_mutex_destroy()pthread_mutex_lock()pthread_mutex_unlock()这四个函数的封装:

    #include "MutexLock.h"
    MutexLock::MutexLock():isLocking_(false)
    {
        CHECK(!pthread_mutex_init(&mutex_,NULL));
    }
    MutexLock::~MutexLock()
    {
        assert(!isLocking());
        CHECK(!pthread_mutex_destroy(&mutex_));
    }
    void MutexLock::lock() { CHECK(!pthread_mutex_lock(&mutex_))//先加锁再修改状态,保证以下赋值操作的原子性。 isLocking_=true; } void MutexLock::unlock() { isLocking_=false;//先修改状态在解锁,保证赋值操作的原子性。 CHECK(!pthread_mutex_unlock(&mutex_)); }

    封装以后,我们使用:

    MutexLockGurad lock(mutex);//就是  MutexLock对象被另一个对象管理
    对临界区进行加锁,而只要我们控制好lock变量的生存期,就能控制临界区,例如:
    int count=0;
    {
        MutexLockGurad lock(mutex);
        count++;
    }//临界区
    //...
    //离开lock的作用域,lock作为栈上变量,自动释放,调用析构函数,同时释放锁。






     

  • 相关阅读:
    ChemDraw绘制DNA结构的技巧
    几何画板中该如何插入公式
    MathType可以编辑带圈乘号吗
    几何画板是这样构造扇形内部的
    Chem 3D软件可以改变背景吗
    移动端上下滑动事件之--坑爹的touch.js
    在HTML5中如何提高网站前端性能
    git入门
    php 路由实现
    vb 定时执行php程序
  • 原文地址:https://www.cnblogs.com/zhangkele/p/9367758.html
Copyright © 2011-2022 走看看