mempool
我刚才在想两个线程同时访问一个函数有没有问题 看到这个我就放心了 其实你可以这样想,函数本身只是代码,代码是只读的,无论多少个线程同时调都无所谓(因为只读嘛)。但是函数里面总要用到数据, 如果数据属于线程(比如函数参数、局部变量,存在栈上,每个线程都有自己的栈),那么同时调还是没关系,因为用的本线程的数据;但是如果用了一些全局数据,比如全局变量,同时操作一个数据结构(如对一个链表有什么操作),那就不行了,这时候锁就出来了。 /////////////////////////////////////////////////////////////// // // I_DataLayer.h // Description: // /////////////////////////////////////////////////////////////// #pragma once #include <plug/plug.h> //------------------------------------------------------------------------------------------------------------------ //#if !defined(...) #ifndef MPMC_MEM_POOL #define MPMC_MEM_POOL #endif #ifdef MPMC_MEM_POOL //多生产者多消费者的多线程模式(支持三个或三个以上线程) #include <boost/lockfree/queue.hpp> #else //单生产者单消费者模式(支持两个线程) #include <boost/lockfree/spsc_queue.hpp> #endif #include <boost/thread.hpp> #include <boost/atomic.hpp> struct mempkt { int size; void* data; }; class memPool { public: memPool(); ~memPool(); private: #ifdef MPMC_MEM_POOL typedef boost::lockfree::queue<mempkt, boost::lockfree::capacity<10000> > memqueue; #else typedef boost::lockfree::spsc_queue<mempkt, boost::lockfree::capacity<10000> > memqueue; #endif void* m_mem_buffer100; memqueue m_mempkt100; void* m_mem_buffer1000; memqueue m_mempkt1000; boost::atomic_int m_buffer100_num; boost::atomic_int m_buffer1000_num; public: inline void* popPkt(int len) { if(len < 100) { void* data = popPkt2(m_mempkt100, len); --m_buffer100_num; return data; } if(len < 1000) { void* data = popPkt2(m_mempkt1000, len); --m_buffer1000_num; return data; } return new char[len];//不再范围内直接自己分配 } void* popPkt2(memqueue& que, int len) { while(1) { if(que.empty())//说明队列中都被取完了,等待别人归还 { boost::this_thread::interruptible_wait(1); continue; } mempkt pkt; if(!que.pop(pkt)) continue; return pkt.data; } return nullptr; } inline void pushPkt(void* data, int len) { if(len < 100) { mempkt pkt = {len, data}; if(m_mempkt100.push(pkt)) { ++m_buffer100_num; return; } if(m_buffer100_num > 9999)//说明队列已经满了,可以等别人来取 boost::this_thread::interruptible_wait(1); } else if(len < 1000) { mempkt pkt = {len, data}; if(m_mempkt1000.push(pkt)) { ++m_buffer1000_num; return; } if(m_buffer1000_num > 9999) boost::this_thread::interruptible_wait(1); } delete[] data; } }; inline memPool::memPool() { m_buffer100_num = 0; m_buffer1000_num = 0; m_mem_buffer100 = new char[1024 * 1024 * 2]; for (int i = 0; i < 10000; i++)//将分配的连续内存分成10000份,每份是100字节 { mempkt pkt; pkt.data = (char*)m_mem_buffer100 + (i * 100);//根据指针的移动 pkt.size = 100; m_mempkt100.push(pkt); } m_mem_buffer1000 = new char[1024 * 1024 * 15]; for (int i = 0; i < 10000; i++)//将分配的连续内存分成10000份,每份是1000字节 { mempkt pkt; pkt.data = (char*)m_mem_buffer1000 + (i * 1000); pkt.size = 1000; m_mempkt1000.push(pkt); } } inline memPool::~memPool() { } #include "mempool.h" #include <boost/lockfree/spsc_queue.hpp> #include <thread> using namespace std; /* 基本思想是分配两块内存,然后将分别将其分割到一个无锁队列中 然后一个线程从里面pop,一个从里面push 注意这里面的线程安全,里面用了原子的int,和无锁,不然会造成不安全 */ struct pakcet { void* data; int len; }; boost::lockfree::spsc_queue<pakcet, boost::lockfree::capacity<22000> > allpakcet;//所有的包存储在allpakcet,单生产者,单消费者模式 int num = 0; memPool *p = new memPool; void getpakcet() { while(1) { if(allpakcet.empty()) { Sleep(1); continue; } pakcet pa; allpakcet.pop(pa); int num = *(int*)pa.data; p->pushPkt(pa.data, pa.len);//同时访问代码段,然后每个线程有调用堆栈,所以多个线程 std::cout << num << std::endl; } } int main() { //线程专门负责取数据 std::thread th(getpakcet); //memPool p; //主线程 while(1) { pakcet pa; pa.data = p->popPkt(sizeof(num)); *(int*)pa.data = num++; pa.len = 4; while(1) { if(allpakcet.push(pa)) break; Sleep(1); } } getchar(); return 0; }