多线程
编译时要链接上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