脑子都想破的资源释放问题

时间:2021-03-14 05:02:36
我有一个资源池(其实就是内存块啦),每块内存都有一个可用标志(比如小于2就可以使用,大于2表示已占用),在我的程序里对于同一块内存有2个以上的线程在操作(操作不同地方,所以没有问题),现在的问题是,这些线程最后一个完成处理的,必须保证把这块内存再归还到资源池中去,这些线程的结束顺序不定,这次A线程先结束,下次可能是B线程先结束,兄弟迂钝,想破脑子还想不通怎么实现资源的无冲突释放,也就是说最好是后结束的线程来释放(咦,它怎么知道它是最后一个呢),请哪位高人来指点一下,假设这块内存是一个大结构体,可以放一些标志字段。
或者有别的办法能借鉴一下也行

20 个解决方案

#1


用Semaphore不就可以了

#2


设一标志位

使用前检查并增加标志位
使用后减小标志位,检查如果为0,也就是说该线程是最后一个使用者,释放

#3


class CAutoBuffer
{
public:
void Copy(BYTE*_buff,DWORD _len);
DWORD GetLen();
char* GetBuff();
CAutoBuffer(BYTE *_buff,DWORD _len)
{
m_bCopy = FALSE;
m_len =0;
m_buff =0;
m_tick =0;
Copy(_buff,_len);
};
void SetTickCount(long _count);
void Release();
void AddRef();
BYTE* Detatch();
void Attatch(BYTE *_buff,DWORD _len);
CAutoBuffer();
virtual ~CAutoBuffer();
long m_param[2];
protected:
BOOL m_bCopy;
BYTE* m_buff;
DWORD m_len;
long m_tick;



};
//
.cpp
#include "stdafx.h"
#include "capMiddle.h"
#include "AutoBuffer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAutoBuffer::CAutoBuffer()
{
m_buff = NULL;
m_len = 0;
m_tick = 0;
m_bCopy = FALSE;

}

CAutoBuffer::~CAutoBuffer()
{

}

void CAutoBuffer::Attatch(BYTE *_buff, DWORD _len)
{
m_bCopy = FALSE;
ASSERT(m_len == 0);
ASSERT(m_buff == NULL);
m_buff = _buff;
m_len = _len;

}

BYTE* CAutoBuffer::Detatch()
{
ASSERT(m_len);
ASSERT(m_buff);
return m_buff;
}

void CAutoBuffer::AddRef()
{
InterlockedIncrement(&m_tick);
}

void CAutoBuffer::Release()
{
InterlockedDecrement(&m_tick);
if(m_tick == 0)
{
if(m_len && m_buff && m_bCopy)
{
delete m_buff;
m_buff = NULL;
m_len = 0;
m_bCopy = FALSE;
}
delete this;
}
}

void CAutoBuffer::SetTickCount(long _count)
{
m_tick = _count;
}

char* CAutoBuffer::GetBuff()
{
return (char*)m_buff;

}

DWORD CAutoBuffer::GetLen()
{
return m_len;
}

void CAutoBuffer::Copy(BYTE *_buff, DWORD _len)
{
m_bCopy = TRUE;
ASSERT(m_len == 0);
ASSERT(m_buff == NULL);
m_buff = new BYTE[_len];
memcpy(m_buff , _buff,_len);
m_len = _len;
}

#4


如果知道将用有几次调用,就先用SetTickCount()设置调用次数,每次用完以后调用release.这样,当里面的计数为0时,他会自动释放他包含的内存,并释放自己。

#5


用semaphore不行啊,因为我没有时间去等待
Deadwolf的方法,不要用临界区去保护这个值么,如果要保护,那也不行,因为这个临界资源会成为瓶颈

#6


调用次数为1-3之间,但这中间可能会重复用,也就是说,每个线程可能重复进入,进来干点事情,然后又退出去(因为它有很多类似的块由它管理)

#7


晕,被楼上抢先,
设个计数器,
每创建线程,就+1,
线程推出就-1,
临界的时候判断,就释放,
这些操作可以需要线程同步处理,
我们的程序中对每个视频回放窗口就是这么处理的

#8


可以再创建一个监视线程,监视所有工作线程,
所有工作线程都激发后,释放资源不就得了。
监视线程也简单得很:
DWORD WINAPI Shit_Thread(LPVOID lpParam)
{
  //等待着您那10个该死的线程死掉!!
  if (WaitForMultipleObjects(10,g_hThread,TRUE,WAIT_INFINITE)
  {
    //在这里释放资源...........
  }
}

#9


不好意思,我的线程也是从线程池中唤醒的,因为全部都是异步操作,所以不能有太占时间的操作,否则它们处理起来就不顺畅了

#10


让你创建个监视线程与线程池有关系吗?
实在不行就在线程里创建子线程啊。。。
难道子线程也从线程池里唤醒吗??!!

#11


呵呵 偶在D版 有给你回答 也可以看看。。

#12


哈哈,楼上的,谢谢

#13


哎,楼上已经有人回答了,其实微软也是这么做的,就是做个记数器,微软对dll的释放也是才用这种方式,当有进程LoadLibray的时候,就给那个dll计数器加个1,当这个进程退出的时候,再减个1,当为0的时候,就释放!

#14


那是不是应该是另外的线程来监控这个计数器呢,因为使用这个计数器的线程有可能同时-1,然后都检测到为0,有无这种可能?

#15


你线程退出的时候告诉一下主线程我退出了,主线程维护这个线程计数,为0就释放。

#16


作一个计数器计数...

#17


信号量

#18


呵呵,差不多有眉目了,这么多人关注,哈哈,不错,多谢

#19


嘿嘿。。

#20


解决了吗?那恭喜

#1


用Semaphore不就可以了

#2


设一标志位

使用前检查并增加标志位
使用后减小标志位,检查如果为0,也就是说该线程是最后一个使用者,释放

#3


class CAutoBuffer
{
public:
void Copy(BYTE*_buff,DWORD _len);
DWORD GetLen();
char* GetBuff();
CAutoBuffer(BYTE *_buff,DWORD _len)
{
m_bCopy = FALSE;
m_len =0;
m_buff =0;
m_tick =0;
Copy(_buff,_len);
};
void SetTickCount(long _count);
void Release();
void AddRef();
BYTE* Detatch();
void Attatch(BYTE *_buff,DWORD _len);
CAutoBuffer();
virtual ~CAutoBuffer();
long m_param[2];
protected:
BOOL m_bCopy;
BYTE* m_buff;
DWORD m_len;
long m_tick;



};
//
.cpp
#include "stdafx.h"
#include "capMiddle.h"
#include "AutoBuffer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAutoBuffer::CAutoBuffer()
{
m_buff = NULL;
m_len = 0;
m_tick = 0;
m_bCopy = FALSE;

}

CAutoBuffer::~CAutoBuffer()
{

}

void CAutoBuffer::Attatch(BYTE *_buff, DWORD _len)
{
m_bCopy = FALSE;
ASSERT(m_len == 0);
ASSERT(m_buff == NULL);
m_buff = _buff;
m_len = _len;

}

BYTE* CAutoBuffer::Detatch()
{
ASSERT(m_len);
ASSERT(m_buff);
return m_buff;
}

void CAutoBuffer::AddRef()
{
InterlockedIncrement(&m_tick);
}

void CAutoBuffer::Release()
{
InterlockedDecrement(&m_tick);
if(m_tick == 0)
{
if(m_len && m_buff && m_bCopy)
{
delete m_buff;
m_buff = NULL;
m_len = 0;
m_bCopy = FALSE;
}
delete this;
}
}

void CAutoBuffer::SetTickCount(long _count)
{
m_tick = _count;
}

char* CAutoBuffer::GetBuff()
{
return (char*)m_buff;

}

DWORD CAutoBuffer::GetLen()
{
return m_len;
}

void CAutoBuffer::Copy(BYTE *_buff, DWORD _len)
{
m_bCopy = TRUE;
ASSERT(m_len == 0);
ASSERT(m_buff == NULL);
m_buff = new BYTE[_len];
memcpy(m_buff , _buff,_len);
m_len = _len;
}

#4


如果知道将用有几次调用,就先用SetTickCount()设置调用次数,每次用完以后调用release.这样,当里面的计数为0时,他会自动释放他包含的内存,并释放自己。

#5


用semaphore不行啊,因为我没有时间去等待
Deadwolf的方法,不要用临界区去保护这个值么,如果要保护,那也不行,因为这个临界资源会成为瓶颈

#6


调用次数为1-3之间,但这中间可能会重复用,也就是说,每个线程可能重复进入,进来干点事情,然后又退出去(因为它有很多类似的块由它管理)

#7


晕,被楼上抢先,
设个计数器,
每创建线程,就+1,
线程推出就-1,
临界的时候判断,就释放,
这些操作可以需要线程同步处理,
我们的程序中对每个视频回放窗口就是这么处理的

#8


可以再创建一个监视线程,监视所有工作线程,
所有工作线程都激发后,释放资源不就得了。
监视线程也简单得很:
DWORD WINAPI Shit_Thread(LPVOID lpParam)
{
  //等待着您那10个该死的线程死掉!!
  if (WaitForMultipleObjects(10,g_hThread,TRUE,WAIT_INFINITE)
  {
    //在这里释放资源...........
  }
}

#9


不好意思,我的线程也是从线程池中唤醒的,因为全部都是异步操作,所以不能有太占时间的操作,否则它们处理起来就不顺畅了

#10


让你创建个监视线程与线程池有关系吗?
实在不行就在线程里创建子线程啊。。。
难道子线程也从线程池里唤醒吗??!!

#11


呵呵 偶在D版 有给你回答 也可以看看。。

#12


哈哈,楼上的,谢谢

#13


哎,楼上已经有人回答了,其实微软也是这么做的,就是做个记数器,微软对dll的释放也是才用这种方式,当有进程LoadLibray的时候,就给那个dll计数器加个1,当这个进程退出的时候,再减个1,当为0的时候,就释放!

#14


那是不是应该是另外的线程来监控这个计数器呢,因为使用这个计数器的线程有可能同时-1,然后都检测到为0,有无这种可能?

#15


你线程退出的时候告诉一下主线程我退出了,主线程维护这个线程计数,为0就释放。

#16


作一个计数器计数...

#17


信号量

#18


呵呵,差不多有眉目了,这么多人关注,哈哈,不错,多谢

#19


嘿嘿。。

#20


解决了吗?那恭喜

#21