• 利用C++11 实现:迷你线程池+CAS自旋锁


    1. 概述

    最近有学习一些关于C++11从语法层面上提供的多线程编程。本来考虑使用C++11的互斥锁来实现线程间的互斥,而C++提供的互斥锁是比较简单的,和Linux的使用没有太大区别。

    另一方面,在面试的时候,会涉及一些无锁的互斥手法。比如:在webserver项目中,请求队列的任务在出队和入队上都需要互斥锁。而互斥锁比较重,需要执行系统调用。而系统调用又需要陷入内核态,调度完切换回用户态又需要时间,因此效率较低。这时候,采用CAS+自旋锁的手法效率会比较高。

    因此,下面的例子借鉴陈硕大神在muduo网络库实现一个迷你版的线程池。在这个线程池中,我们把线程类Thread线程池类ThreadPool进行解耦,让模块与模块之间的耦合度更低。在实现细节上:

    1. 其中,ThreadPool类定义了线程池中的子线程的工作函数runInThread,这个在muduo网络库里面其实是开发了个接口给用户进行定义的,但是在这里我们没有提供这个借口,感兴趣的读者可以自行拓展封装。

    2. 我们实现了一个CAS类的自旋锁,其实现使用了C++11提供的原子类atomic

    2. 代码实现

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    int mutex = 0;
    int lock = 1;
    int unlock = 0;
    
    class CAS {
    public:
    	CAS() : flag(false) {}
    
    	// 上锁
    	void lock() {
    		bool expect = false;
    		// 1. 如果flag的值(锁的值)和期望的值相等,那么将新的值赋给flag,返回true
    		// 2. 如果flag的值(锁的值)和期望值不相等,那么将flag的值赋给expect,返回false,因此每次都要重置expect
    		while (!flag.compare_exchange_weak(expect, true)) {
    			expect = false;
    		}
    	}
    
    	// 解锁
    	void unlock() {
    		flag.store(false);
    	}
    
    private:
    	CAS(const CAS&) = delete;
    	CAS& operator=(const CAS&) = delete;
    	atomic<bool> flag; // false为解锁状态 true为上锁状态
    };
    
    
    class Thread {
    public:
    	Thread(function<void()> func) : func_(func) {}
    
    	thread start() {
    		thread t(func_);
    		return t;
    	}
    
    private:
    	function<void()> func_;
    };
    
    class ThreadPool {
    public:
    
    	void startPool(int poolSize) {
    		for (int i = 0; i < poolSize; ++i) {
    			pool_.push_back(new Thread(bind(&ThreadPool::runInPool, this, i)));
    		}
    
    		for (int i = 0; i < poolSize; ++i) {
    			handler_.push_back(pool_[i]->start());
    		}
    
    		for (int i = 0; i < poolSize; ++i) {
    			handler_[i].join();
    		}
    	}
    
    private:
    	// 工作函数
    	void runInPool(int threadId) {
    		mutex_.lock();
    		cout << "Thread start! Thread Id:" << threadId << endl;
    		mutex_.unlock();
    	}
    
    	vector<Thread*> pool_;
    	vector<thread> handler_;
    
    	CAS mutex_;
    };
    
    
    int main() {
    
    	ThreadPool pool;
    	pool.startPool(10);
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
  • 相关阅读:
    Vuex状态刷新状态丢失的处理方法
    SpringBoot利用Spring SPI机制实现自动按顺序加载注册JavaBean到容器中
    【老生谈算法】matlabBOOST电路的设计与仿真——BOOST电路
    Reinforcement learning from demonstration through shaping(Wiewiora 2003)
    Java.lang ClassLoader findLibrary()方法具有什么功能呢?
    建信多因子量化股票有什么作用?
    回文 马蹄集
    基于Python实现的KNN分类实验
    逆向分析 工具、加壳、安全防护篇
    【HMS Core】集成地图服务不显示地图问题
  • 原文地址:https://blog.csdn.net/zsiming/article/details/126612407