Linux 多线程Posix详解(三) : C++封装

24 篇文章 1 订阅

Posix多线程系列文章:
Linux 多线程Posix详解(一) : 线程的创建、等待、退出、取消与清理
Linux 多线程Posix详解(二) : 线程的同步与互斥
Linux 多线程Posix详解(三) : C++封装


一.前言

在使用多线程的过程中,如果每一次都需要使用 pthread_create, pthread_cond_wait 这样的语句未免显得太过麻烦,于是将线程,锁进行封装,将其内部实现隐藏,需要的时候便能够直接使用。此篇文章主要封装三个类:

  • 线程类
  • 锁类
  • 条件变量类

另外,此篇文章主要以面向对象的方式进行封装,如果想使用多线程的基于对象方式封装类,请访问我的github:
https://github.com/Worthy-Wang/MultiThread

头文件 Noncopyable.h 删除了拷贝复制函数 与 拷贝复制运算符,派生类继承后也将不能使用这两个函数。
Noncopyable.h:

#pragma once

/*
不可拷贝基类:继承此基类的派生类将不能使用拷贝构造函数与拷贝赋值运算符
*/

namespace wd
{
    class Noncopyable
    {
    protected:
        Noncopyable() {}
        ~Noncopyable() {}
        Noncopyable(const Noncopyable &lhs) = delete;
        const Noncopyable &operator=(const Noncopyable &lhs) = delete;
    };
} // namespace wd


二.线程类 Thread

线程类(虚基类):
调用start函数时,创建线程并调用静态threadFunc函数,在threadFunc函数中调用纯虚函数run,当有
派生类继承虚基类Thread的时候,只需要覆盖run函数即可创建线程运行run函数,非常方便。

Thread.h:

#pragma once
#include <pthread.h>
#include <iostream>
#include "Noncopyable.h"

/*

*/

namespace wd
{
    class Thread
        : Noncopyable
    {
    public:
        Thread();
        virtual ~Thread();
        void start();
        void join();

    private:
        pthread_t _pid;
        bool _isRunning;
        virtual void run() = 0;
        static void *threadFunc(void * arg);
    };

} // namespace wd

Thread.cpp:

#include "Thread.h"

namespace wd
{
    Thread::Thread()
        : _pid(0), _isRunning(false)
    {
        std::cout << "Thread()" << std::endl;
    }

    Thread::~Thread()
    {
        if (_isRunning)
        {
            if (pthread_detach(_pid))
            {
                perror("pthread_detach");
                return;
            }
            _isRunning = false;
            std::cout << "~Thread()" << std::endl;
        }
    }

    void Thread::start()
    {
        if (!_isRunning)
        {
            if (pthread_create(&_pid, NULL, threadFunc, this))
            {
                perror("pthread_create");
                return;
            }
            _isRunning = true;
        }
    }

    void Thread::join()
    {
        if (_isRunning)
        {
            if (pthread_join(_pid, NULL))
            {
                perror("pthread_join");
                return;
            }
            _isRunning = false;
            std::cout << "join()" << std::endl;
        }
    }

    void *Thread::threadFunc(void *arg)
    {
        Thread *p = static_cast<Thread *>(arg);
        p->run();
        return NULL;
    }
} // namespace wd

利用任务类继承并重载run函数,就能够开启子线程并运行run函数,记得在编译的时候加上 -lpthread
main.cpp:

#include "Noncopyable.h"
#include "Thread.h"
#include <iostream>
#include <unistd.h>
#include <memory>

class MyThread
:public wd::Thread
{
private:
    void run() override
    {
        while (1)
        {
            srand(time(NULL));
            std::cout << rand() % 100 << std::endl;
            sleep(1);
        }
    }
};


int main()
{
    std::unique_ptr<MyThread> p1(new MyThread());
    p1->start();
    p1->join();
    return 0;
}

二.锁类 MutexLock

封装锁类的时候需要注意一个问题:如果手动进行加解锁,那么如果因为系统中断导致无法解锁,那么就会形成死锁了。
在这里我们利用另一个类的生命周期来对锁进行加解锁。

MutexLockGuard?
在生成MutexLockGuard类对象之后,自动加锁,然后在语句块中执行完毕,调用析构函数的时候自动解锁,这样自动加解锁,避免了死锁的可能

MutexLock.h:

#pragma once
#include <pthread.h>
#include <stdio.h>
#include "Noncopyable.h"
/*
封装mutex类,并创建类MutexLockGuard用来实现锁(MutexLock类加解锁不再对外开放),这样可以有效防止死锁
*/

namespace wd
{
    class MutexLock
        : Noncopyable
    {
    public:
        MutexLock()
            : _isLocking(false)
        {
            if (pthread_mutex_init(&_mutex, NULL))
            {
                perror("pthread_mutex_init");
                return;
            }
        }

        ~MutexLock()
        {
            if (pthread_mutex_destroy(&_mutex))
            {
                perror("pthread_mutex_destroy");
                return;
            }
        }

        void lock()
        {
            if (pthread_mutex_lock(&_mutex))
            {
                perror("pthread_mutex_lock");
                return;
            }
            _isLocking = true;
        }

        void unlock()
        {
            if (pthread_mutex_unlock(&_mutex))
            {
                perror("pthread_mutex_unlock");
                return;
            }
            _isLocking = false;
        }

        bool isLocking() const { return _isLocking; }
        pthread_mutex_t *getMutexPtr() { return &_mutex; }

    private:
        pthread_mutex_t _mutex;
        bool _isLocking;
    };

    class MutexLockGuard
    {
    public:
        MutexLockGuard(MutexLock &mutexlock)
            : _mutexlock(mutexlock)
        {
            _mutexlock.lock();
        }

        ~MutexLockGuard()
        {
            _mutexlock.unlock();
        }

    private:
        MutexLock &_mutexlock;
    };
} // namespace wd

三.条件变量类 Condition

Condition类需要和MutexLock类进行一起使用,这样才能完成线程的同步。
Condition.h:

#pragma once
#include "Noncopyable.h"
#include "MutexLock.h"

namespace wd
{
    class Condition
    : Noncopyable
    {
    public:
        Condition(MutexLock& mutexlock)
        :_mutexlock(mutexlock)
        {
            if (pthread_cond_init(&_cond, NULL))
            {
                perror("pthread_cond_init");
                return;
            }
        }

        ~Condition()
        {
            if (pthread_cond_destroy(&_cond))
            {
                perror("pthread_cond_destroy");
                return;
            }
        }

        void wait()
        {
            if (pthread_cond_wait(&_cond, _mutexlock.getMutexPtr()))
            {
                perror("pthread_cond_wait");
                return;
            }
        }

        void notify()
        {
            if (pthread_cond_signal(&_cond))
            {
                perror("pthread_cond_signal");
                return;
            }
        }

        void notifyAll()
        {
            if (pthread_cond_broadcast(&_cond))
            {
                perror("pthread_cond_broadcast");
                return;
            }
        }

    private:
        pthread_cond_t _cond;
        MutexLock& _mutexlock;
    };
} // namespace wd
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值