多线程~~

本文介绍了多线程编程的基础知识,包括如何使用pthread库创建线程,线程的join和detach状态,以及线程信息的查看。接着,展示了生产者消费者模型的实现,利用条件变量协调生产者和消费者的同步。此外,讨论了信号量在资源管理中的应用,并给出了线程池的概念和简单实现。最后,提到了C++中的单例模式,用于确保类只有一个实例并提供全局访问点。
摘要由CSDN通过智能技术生成

多线程

在这里插入图片描述
编译时要链接上pthread库, gcc thread.c -o thread -l pthread

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_entry(void*arg)//线程运行的函数
{
  while(1){
    printf("i am child thread:%s\n",arg);
    sleep(1);
  }
  return NULL;
}
int main()
{
  //int pthread_create(pthread_t * tid, pthread_attr_t * attr, void* (*routine)(void*), void *agr)
  pthread_t tid;
  char* arg="你好!";

  int ret=pthread_create(&tid,NULL,thread_entry,(void*)arg);
  if(ret!=0)
  {
    printf("pthread create error!\n");
    return -1;
  }
  //线程一旦创建成功了,创建成出来的线程调度的是传入的线程入口函数,
  while(1)
  {
    printf("i am a main thread\n");
    sleep(1);
  }
  return 0;
}

带信息头的查看线程信息
ps -efL | head -n 1 && ps -efL|grep thread

pthread_exit
在这里插入图片描述

pthread_cancel
在这里插入图片描述
更详细的线程信息
ps -efL -l | head -n 1 && ps -efL -l | grep thread

在这里插入图片描述
等待:等待指定线程退出,获取退出返回值,回收未被完全释放的资源
在线程中,有个分离属性,默认值是joinable状态,表示线程退出后不会自动释放所有资源,需要被其他线程等待
pthread_join
等待线程指定的线程终止
在这里插入图片描述
分离:将线程的分离属性社会为detach,表示线程退出后自动释放所有资源,则这种线程退出后不需要被等待(不关心其返回值时采用)
pthread_detach
分离一个线程
在这里插入图片描述

在这里插入图片描述

生产者消费者模型

在这里插入图片描述
Product_and_consumer.cpp

#include<iostream>
using namespace std;
#include<pthread.h>
#include<queue>
template<class T>
class BlockQueue{
  public:
    BlockQueue(int capacity):_capacity(capacity){
      pthread_mutex_init(&_mutex,NULL);
      pthread_cond_init(&_cond_pro,NULL);
      pthread_cond_init(&_cond_con,NULL);
    };
    ~BlockQueue(){
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_pro);
      pthread_cond_destroy(&_cond_con);
    };
    bool Push(const T & data){//push是生产者线程运行的
      pthread_mutex_lock(&_mutex);
      while(_capacity==_q.size()){//容量达到队列上限就要停止生产,唤醒消费者线程
        pthread_cond_wait(&_cond_pro,&_mutex);//阻塞生产者进程

      }
      _q.push(data);
      cout<<"+++++"<<pthread_self()<<"thread get data:"<<data<<endl;
      pthread_cond_signal(&_cond_con);//唤醒消费者进程
      pthread_mutex_unlock(&_mutex);

    };
    bool Pop(T* data){
      pthread_mutex_lock(&_mutex);
      while(_q.empty()){
        pthread_cond_wait(&_cond_con,&_mutex);
      }
      *data=_q.front();
      _q.pop();

      cout<<"-----"<<pthread_self()<<"thread get data:"<<*data<<endl;
      pthread_cond_signal(&_cond_pro);
      pthread_mutex_unlock(&_mutex);
    };
  private:
    queue<T> _q;
    int _capacity;
    pthread_mutex_t _mutex;//互斥锁
    pthread_cond_t _cond_pro;//生产者同步变量
    pthread_cond_t _cond_con;//消费者:
};

#define MAX_USER 4
void * consumer(void* arg)
{
  BlockQueue<int> *q=(BlockQueue<int> *)arg;
  while(1){
    int data;
    q->Pop(&data);
  }

  return NULL;
}

void * productor(void* arg)
{
  BlockQueue<int> *q = (BlockQueue<int> *)arg;
  int data=0;
  while(1){
    q->Push(data++);
  }
  return NULL;
}

int main()
{
  BlockQueue<int> q(5);
  pthread_t cond_tid[MAX_USER],pro_tid[MAX_USER];
  int ret;
  for(int i=0;i<MAX_USER;i++){
    ret=pthread_create(&cond_tid[i],NULL,consumer,(void*)&q);
    if(ret!=0){
      std::cout<<"pthread_create error\n";
      return -1;
    }
    ret=pthread_create(&pro_tid[i],NULL,productor,(void*)&q);
    if(ret!=0){
      std::cout<<"pthread_create error\n";
      return -1;
    }
  }
  for(int i=0;i<MAX_USER;i++){
    pthread_join(cond_tid[i],NULL);
    pthread_join(pro_tid[i],NULL);
  }
  return 0;
}


信号量

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<vector>
#include<pthread.h>
#include<semaphore.h>

template<class T>
class RingQueue{
  private:
    std::vector<int> _arr;
    int _read_step;
    int _write_step;
    int _capacity;
    sem_t _sem_data;
    sem_t _sem_idle;
    sem_t _sem_lock;
  public:
    RingQueue(int capacity):_capacity(capacity),_arr(capacity),_read_step(0),_write_step(0){
      sem_init(&_sem_idle,0,capacity);
      sem_init(&_sem_data,0,0);
      sem_init(&_sem_lock,0,1);
    }
    ~RingQueue(){
      sem_destroy(&_sem_idle);
      sem_destroy(&_sem_data);
      sem_destroy(&_sem_lock);
    }
    bool Push(const T& data){
      sem_wait(&_sem_lock);
      sem_wait(&_sem_idle);
      _arr[_write_step]=data;
      _write_step=(_write_step+1)%_capacity;
      sem_post(&_sem_data);
      sem_post(&_sem_lock);
      return true;
    }
    bool Pop(T* data){
      sem_wait(&_sem_lock);
      sem_wait(&_sem_data);
      *data=_arr(_read_step+1)%_capacity;
      sem_post(&_sem_idle);
      sem_post(&_sem_lock);
      return true;
    }

};

线程池

在这里插入图片描述

template<class T>//线程池只是一个执行流的池子,本身并不知道一个任务该如何处理,因此设计一个任务类
class ThreadTask{
	private:
		T _data;//处理的数据
		std::function<void(T)> _handler;//任务处理方法
	public:
		void start(){ return _handler(_data) }; 
};
class ThreadPool{
	private:
		int _max_thread;//线程的数量
		BlockQueue< ThreadTask<T> > _queue;
	public:
		ThreadPool(){//完成线程的创建}
		bool Push(ThreadTask<T> & task);
};

//
// Created by AIERXUAN on 2023/3/11.
//
#include <iostream>
#include<queue>
#include <functional>
#include <utility>
#include<unistd.h>
#include<pthread.h>

#define MAX_QUEUE 5;

using namespace std;

template<class T>
class BlockQueue {
private:
    queue<T> _q;
    int _capacity;//队列容量限制
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;
    pthread_cond_t _cond_con;
public:
    BlockQueue(int capacity):_capacity(capacity){
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond_pro, nullptr);
            pthread_cond_init(&_cond_con, nullptr);
    }

    ~BlockQueue() {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond_pro);
        pthread_cond_destroy(&_cond_con);
    }

    void Push(const T &data) {//生产者,队满停止生产
        pthread_mutex_lock(&_mutex);
        while (_capacity == _q.size()) {
            pthread_cond_wait(&_cond_pro, &_mutex);
        }
        _q.push(data);
        pthread_cond_signal(&_cond_con);
        pthread_mutex_unlock(&_mutex);
    }

    void Pop(T *data) {//出队操作,消费者,队不空才可以出队,队空阻塞唤醒生产者
        pthread_mutex_lock(&_mutex);
        while (_q.empty()) {
            pthread_cond_wait(&_cond_pro, &_mutex);
        }
        *data = _q.front();
        _q.pop();
        pthread_cond_signal(&_cond_pro);
        pthread_mutex_unlock(&_mutex);
    }
};

template<class T>
class ThreadTask {

public:
    using Handler = function<void(T)>;
    /*等价于 Handler = std::funtional<void (T)> ;  定义了一个函数类型*/

    ThreadTask() = default;

    ThreadTask(const T &data, Handler handler) : _data(data), _handler(std::move(handler)) {}

    void Start() {
        return _handler(_data);
    }

private:
    T _data{};
    Handler _handler;
};

template<class T>
class ThreadPool {
private:
    int _thread_max;
    BlockQueue<ThreadTask<T>> _queue;//线程安全的任务队列
    vector<pthread_t> _tid;//保存所有线程的tid
private:
    static void *thread_entry(void *arg) {//循环从任务队列中取出任务调用的Start接口进行任务处理
        auto *pool = (ThreadPool *) arg;
        while (1) {
            ThreadTask<T> task;
            pool->_queue.Pop(&task);//无效的静态成员函数中访问了非静态成员变量
            task.Start();
        }
        return nullptr;
    }

public:
    //完成创建指定数量的线程
    ThreadPool(int thread_max, int queue_max) : _thread_max(thread_max), _queue(queue_max) {
        int ret;
        pthread_t tid;
        for (int i = 0; i < thread_max; ++i) {
            ret = pthread_create(&tid, nullptr, thread_entry, this);
            if (ret != 0) {
                cout << "create thread failed!\n";
                exit(-1);
            }
        }
    }

    bool Push(ThreadTask<T> &task) {//任务入队
        _queue.Push(task);
        return true;
    }
};

void print_test(int data) {
    printf("%llu thread ,run data:%d\n",pthread_self(),data);
    sleep((data % 3) + 1);
}


int main() {
    ThreadPool<int> pool(5, 10);
    for (int i = 0; i < 10; ++i) {
        ThreadTask<int> task(i, print_test);
        pool.Push((task));
    }
    sleep(10);
    return 0;
}

单例模式

Ensure a class has only one instance and provide a global point of access to it.
确保类只有一个实例,并提供对它的全局访问点。

#include <iostream>
#include <mutex>

using namespace std;

//class Singleton {//饿汉模式
//private:
//    string _data;
//private:
//    static Singleton _eton;//静态成员
//
//    Singleton() {//构造函数私有化,类外无法实例化对象,保证一个类只能实例化一个对象
//        _data = “饿汉”;
//    }
//
//public:
//    string get_data() { return _data; }
//
//    static Singleton *GetInstance() {
//        return &_eton;
//    }
//};
//
//Singleton Singleton::_eton;//静态变量在类外定义


class Singleton {
private:
    string _data="懒汉";
    static Singleton *_eton;
    static std::mutex _mutex;
public:
    string get_data() { return _data; }

    static Singleton *GetInstance() {
        if (_eton == NULL)
            _mutex.lock();//保证实例化过程的线程安全问题,
        if (_eton == NULL) {
            _eton = new Singleton;
        }
        _mutex.unlock();
        return _eton;
    }
};

Singleton *Singleton::_eton = nullptr;
std::mutex Singleton::_mutex;
int main() {
    Singleton *singleton = Singleton::GetInstance();
    std::cout << singleton->get_data() << std::endl;
    return 0;
}

总结

在这里插入图片描述

替换掉每行首的所有空格及数字

VIM底行模式下

:1,$s/^\s*[0-9]\s//g

解释:1为起始行号,315为终止行号,在正则中代表行首,\s*代表若干个空格,可以没有,[0-9]*代表若干个数字,可以没有,即将\s*[0-9]\s替换为NOTHING。

或者:

:%s/^…//g

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值