我刚才在想两个线程同时访问一个函数有没有问题
看到这个我就放心了
其实你可以这样想,函数本身只是代码,代码是只读的,无论多少个线程同时调都无所谓(因为只读嘛)。但是函数里面总要用到数据,
如果数据属于线程(比如函数参数、局部变量,存在栈上,每个线程都有自己的栈),那么同时调还是没关系,因为用的本线程的数据;但是如果用了一些全局数据,比如全局变量,同时操作一个数据结构(如对一个链表有什么操作),那就不行了,这时候锁就出来了。
///////////////////////////////////////////////////////////////
//
// 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;
}