C++线程相关函数介绍与封装,多线程实现抢票系统(需要修改版)

功能:创建一个新的线程
原型
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);
参数
 thread:返回线程ID
 attr:设置线程的属性,attr为NULL表示使用默认属性
 start_routine:是个函数地址,线程启动后要执行的函数
 arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
功能:等待线程结束
原型 int pthread_join(pthread_t thread, void **value_ptr);
参数 thread:线程ID
     value_ptr:它指向一个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
功能:线程终止
原型
 void pthread_exit(void *value_ptr);
参数
 value_ptr:value_ptr不要指向一个局部变量。
返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)
功能:取消一个执行中的线程
原型
 int pthread_cancel(pthread_t thread);
参数
 thread:线程ID
返回值:成功返回0;失败返回错误码

下面简单对线程库进行一下封装

#include <iostream>
#include <string>
#include <unistd.h>
#include <functional>
#include <pthread.h>

namespace ThreadModule
{
    template <typename T>
    using func_t = std::function<void(T &)>;
    //typedef std::function<void(const T&)> func_t;

    template <typename T>
    class Thread
    {
    public:
        void Excute()
        {
            _func(_data);
        }

        Thread(func_t<T> func, T &data, const std::string &name = "none-name")
            : _func(func), _data(data), _threadname(name), _stop(true)
        {
        }
        static void *threadroutine(void *args)
        {
            Thread<T> *self = static_cast<Thread<T> *>(args);
            self->Excute();
            return nullptr;
        }
        bool Start()
        {
            int n = pthread_creat(&_tid, nullptr, threadroutine, this);
            if (!n)
            {
                _stop = false;
                return true;
            }
            else
            {
                return false;
            }
        }
        void Detach()
        {
            if (!_stop)
            {
                pthread_detach(_tid);
            }
        }
        void Join()
        {
            if (!_stop)
            {
                pthread_join(_tid, nullptr);
            }
        }
        std::string name()
        {
            return _threadname;
        }      
        void stop()
        {
            _stop = true;
        }
        ~Thread() {}
    private:
        pthread_t _tid;
        std::string _threadname;
        T &_data; // 让所有线程访问同一个全局变量
        func_t<T> _func;
        bool _stop; // 标记当前线程运行状态
    }
}

下面我们使用自己封装的Thread简单实现一个多线程抢票系统

#include<iostream>
#include<vector>
#include"Thread.hpp"

using namespace ThreadModule;
 int g_tickets = 1000;//总票数,全局的

 void route(int &tickets)
 {
    while(true)
    {
        if(tickets>0)
        {
            usleep(1000);
            printf("get tickets: %d\n",tickets);
            tickets--;
        }
        else
        {
            break;
        }
    }
 }

 const int num = 4;//欲创建线程数量
int main()
{
    std::vector<Thread<int>> threads;
    //创建一批线程
    for(int i = 0;i<num;i++)
    {
        std::string name = "thread-"+std::to_string(i+1);
        threads.emplace_back(route,g_tickets,name);
    }
    //启动线程
    for(auto &thread:threads)
    {
        thread.Start();
    }
    //等待线程
    for(auto &thread : threads)
    {
        thread.Join();
        std::cout<<thread.name()<< : <<"wait down"<<std::endl;
    }

    return 0;
} 

创建了4个线程,每个线程都将并行的执行route函数,直到总票数小于0。

上述代码逻辑上没有问题,但是在执行中它有问题,会出现负数的情况。

所有线程都访问总票数g_ticktes这个全局变量,又因为线程是并行的,可能多个线程都在处理时,前一个线程执行完之后票数已经为0了,但是另一个线程还没执行完,这样就会出现负数的情况。所以我们应该对g_tickats这个变量进行保护,让在同一个时间只有一个线程能够访问它,我们需要用到锁的知识。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值