一、多线程与内存池的结合使用:
一个线程memorymalloc,另一个线程memoryfree,效率是malloc\free的1.3倍(单线程时是3倍,本来双线程应该是6倍,但因为使用了线程的同步,使线程地并发变为了串行,故效率也应是3倍,又线程切换时会遇到阻塞的情况、再加上切换时的消耗,最后得到1.3)
#include
#include
#include
#include
#include
#include "memorypool.h"
#include
time_t start;
time_t end;
int* sum;
int count=0;
sem_t sem1;
sem_t sem2;
memorypool*mp=NULL;
void* fn_0(void* arg)
{
start = time(NULL);
while(1)
{
end = time(NULL);
if(end == start +180)
break;
//sum = (int*)memory_malloc(mp,sizeof(int));
sum = (int*)malloc(sizeof(int));
*sum = 2333;
sem_post(&sem2);
sem_wait(&sem1);
}
return (void*)arg;
}
void* fn_1(void* arg)
{
while (1)
{
end = time(NULL);
if(end == start+180)
break;
sem_wait(&sem2);
//memory_free((char**)&sum);
free(sum);
count +=1;
sem_post(&sem1);
}
printf("count,%d\n",count);
return (void*)arg;
}
int main()
{
mp = memorypool_create(1024,3,1);
pthread_t thread0;
pthread_t thread1;
sem_init(&sem1,0,0);
sem_init(&sem2,0,0);
pthread_create(&thread0, NULL, fn_0, (void*)mp);
pthread_create(&thread1, NULL, fn_1, (void*)mp);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
sem_destroy(&sem1);
sem_destroy(&sem2);
return 0;
}
二、多线程与队列的结合:
#include
#include
#include
#include
#include
#include
#include "memorypoll.h"
#define SizeOfQueue 6
time_t start;
time_t end;
memorypool* mp=NULL;
typedef struct Queue
{
int* data[SizeOfQueue];
int head;
int tail;
int cnt;
}queue;
typedef struct Data
{
queue* que;
pthread_mutex_t mlock;
int count;
}data;
//pthread_mutex_t mlock1;
queue* queue_init()
{
queue* qe = (queue*)malloc(sizeof(queue));
if (NULL == qe)
{
printf("Init queue error");
exit(1);
}
memset(qe, 0, sizeof(queue));
qe->head = 0;
qe->tail = SizeOfQueue - 1;
qe->cnt = 0;
return qe;
};
int en_queue(queue* qe)
{
if (qe->cnt == SizeOfQueue)//判断栈满;
{
return 0;
}
//pthread_mutex_lock(&mlock1);
int* tem = (int*)malloc(sizeof(int));
// int* tem = (int*)memory_malloc(mp,sizeof(int));
*tem = 2333;
//pthread_mutex_unlock(&mlock1);
qe->tail = (qe->tail + 1) % SizeOfQueue;
qe->data[qe->tail] = tem;
qe->cnt += 1;
return 0;
};
int de_queue(queue* qe)
{
int* tmp=NULL;
if (qe->cnt == 0)
{
return 0;
}//判断栈空
tmp = qe->data[qe->head];
//pthread_mutex_lock(&mlock1);
free(tmp);
//memory_free((char**)&tmp);
tmp=NULL;
//pthread_mutex_unlock(&mlock1);
qe->head = (qe->head + 1) % SizeOfQueue;
qe->cnt -= 1;
return 0;
};
void* fn_0(void* arg)
{
data* da1 = (data*)arg;
start = time(NULL);
while(1)
{
end = time(NULL);
if (end == start + 180)
break;
pthread_mutex_lock(&da1->mlock);
en_queue(da1->que);
pthread_mutex_unlock(&da1->mlock);
}
return (void*)da1;
}
void* fn_1(void* arg)
{
data* da2 = (data*)arg;
while (1)
{
end = time(NULL);
if (end == start + 180)
break;
pthread_mutex_lock(&da2->mlock);
de_queue(da2->que);
da2->count +=1;
pthread_mutex_unlock(&da2->mlock);
}
printf("count:%d\n",da2->count);
return (void*)da2;
}
int main()
{
mp = memorypool_create(sizeof(int),7,1);
pthread_t thread0;
pthread_t thread1;
data da;
da.count = 0;
pthread_mutex_init(&da.mlock, NULL);
//pthread_mutex_init(&mlock1, NULL);
da.que = queue_init();
pthread_create(&thread0, NULL, fn_0, (void*)&da);
pthread_create(&thread1, NULL, fn_1, (void*)&da);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
pthread_mutex_destroy(&da.mlock);
//pthread_mutex_destroy(&mlock1);
return 0;
}
三、多线程与队列与内存池的结合:
构思是:一个线程memorymalloc,另一个线程memoryfree,使用队列作为缓冲,互斥锁用来保护
但目前有个BUG尚未解决,看了两天未果,以后再回头来看吧,具体现象如下:
多线程时,内存池初始化时的大小是sizeof(int)时,mp->free_list->mp的值会无故被改成0x91D,导致segmentation fault
单线程时,内存池初始化时的大小是sizeof(int)时,运行正常
多线程时,内存池初始化时的大小是1024时,运行正常
memorypool.h:
#ifndef _MEMORYPOOL_H_
#define _MEMORYPOOL_H_
#include
#include
#include
typedef struct Memorypool
{
int mempool_size;
int memory_size;//block_size + sizeof(manager information) = mem_size
int block_size;
int total_memory_cnt;
int used_memory_cnt;
int auto_extend;
struct Memory* free_list;
struct Memory* used_list;
}memorypool;
typedef struct Memory
{
int memory_size;
int block_size;
struct Memory* prev;
struct Memory* next;
struct Memorypool* mp;
char* block;
}memory;
memorypool* memorypool_create(int block_request_size, int memory_init_quantity, bool memory_extend);
char* memory_malloc(memorypool* mp,int data_size);
int memorypool_info_get(memorypool* mp);
int memory_free(char** p_bk);
int memorypool_destroy(memorypool* mp);
memory* memory_creat(int memory_size, memorypool* mp);
#endif
memorypool.c:
#include "memorypool.h"
memorypool* memorypool_create(int block_request_size, int memory_init_quantity, bool memory_extend)
{
memorypool* mp = NULL;
mp = (memorypool*)malloc(sizeof(memorypool));
memset(mp, 0, sizeof(memorypool));
mp->block_size = block_request_size;
mp->memory_size = block_request_size + sizeof(memory);
mp->auto_extend = memory_extend;
for (int i = memory_init_quantity; i > 0; i--)
{
memory* mm = NULL;
mm = memory_creat(mp->memory_size , mp);
}
return mp;
};
char* memory_malloc(memorypool* mp, int data_size)
{
memory* p_memory = NULL;
if (mp->block_size < data_size)
{
return NULL;
}
if (NULL == mp->free_list)
{
if (mp->auto_extend == 1)
memory_creat(mp->memory_size, mp);
else
return NULL;
}
p_memory = mp->free_list;
mp->free_list = mp->free_list->next;
p_memory->next = NULL;
if (mp->used_list)
{
mp->used_list->prev->next = p_memory;
p_memory->prev = mp->used_list->prev;
}
else
{
mp->used_list = p_memory;
}
p_memory->next = mp->used_list;
mp->used_list->prev = p_memory;
mp->used_list = p_memory;
mp->used_memory_cnt += 1;
return p_memory->block;
};
int memorypool_info_get(memorypool* mp)
{
printf("current mempool_size:%d\n\
current memory_size:%d\n\
current block_size:%d\n\
total_memory_cnt:%d\n\
used_memory_cnt:%d\n",mp->mempool_size,mp->memory_size,mp->block_size, \
mp->total_memory_cnt,mp->used_memory_cnt);
return 0;
};
int memory_free(char** p_bk)
{
memory* p_memory = (memory* )(*p_bk + sizeof(memory));//错误
memory* p_memory = (memory* )(*p_bk - sizeof(memory)/(sizeof(char)));//正确
p_memory->next->prev = p_memory->prev;
p_memory->prev->next = p_memory->next;
p_memory->next = NULL;
p_memory->prev = NULL;
if (p_memory->mp->used_memory_cnt == 1)
p_memory->mp->used_list = NULL;
p_memory->next = p_memory->mp->free_list;
p_memory->mp->free_list = p_memory;
p_memory->mp->used_memory_cnt -= 1;
*p_bk = NULL;
return 0;
};
int memorypool_destroy(memorypool* mp)
{
memory* mm = NULL;
if (mp->free_list)
{
mm = mp->free_list;
mp->free_list = mp->free_list->next;
free(mm);
mm = NULL;
}
if (mp->used_list)
{
mp->used_list->prev->next = NULL;
mm = mp->used_list;
mp->used_list = mp->used_list->next;
free(mm);
mm = NULL;
}
free(mp);
return 0;
}
memory* memory_creat(int memory_size, memorypool* mp)
{
memory* mm = NULL;
char* bk = NULL;
char* memory_start = (char*)malloc(memory_size);
memset(memory_start, 0, memory_size);
mm = (memory*)memory_start;
memset(mm, 0, sizeof(memory));
bk = memory_start - sizeof(memory);//错误
bk =memory_start +sizeof(memory)/(sizeof(char));//正确
mm->memory_size = memory_size;
mm->block_size = memory_size - sizeof(memory);
mm->mp = mp;
printf("mp:%p\n",mp);
printf("mm_mp:%p\n",mm->mp);
mm->block = bk;
mm->next = mp->free_list;
mp->free_list = mm;
mp->total_memory_cnt += 1;
mp->mempool_size += mp->memory_size;
return mm;
};
queue.c:
#include
#include
#include
#include
#include
#include
#include "memorypool.h"
#define SizeOfQueue 6
time_t start;
time_t end;
memorypool* mp=NULL;
typedef struct Queue
{
int* data[SizeOfQueue];
int head;
int tail;
int cnt;
}queue;
typedef struct Data
{
queue* que;
pthread_mutex_t mlock;
int count;
}data;
queue* queue_init()
{
queue* qe = (queue*)malloc(sizeof(queue));
if (NULL == qe)
{
printf("Init queue error");
exit(1);
}
memset(qe, 0, sizeof(queue));
qe->head = 0;
qe->tail = SizeOfQueue - 1;
qe->cnt = 0;
return qe;
};
int en_queue(queue* qe)
{
if (qe->cnt == SizeOfQueue)//判断队列满;
{
return 0;
}
//int* tem = (int*)malloc(sizeof(int));
int* tem = (int*)memory_malloc(mp,sizeof(int));
*tem = 2333;
qe->tail = (qe->tail + 1) % SizeOfQueue;
qe->data[qe->tail] = tem;
qe->cnt += 1;
return 0;
};
int de_queue(queue* qe)
{
int* tmp=NULL;
if (qe->cnt == 0)
{
return 0;
}//判断队列空;
printf("qe->cnt:%d\n",qe->cnt);
tmp = qe->data[qe->head];
//free(tmp);
memory_free((char**)&tmp);
//tmp=NULL;
qe->head = (qe->head + 1) % SizeOfQueue;
qe->cnt -= 1;
return 0;
};
void* fn_0(void* arg)
{
data* da1 = (data*)arg;
start = time(NULL);
while(1)
{
end = time(NULL);
if (end == start + 180)
break;
pthread_mutex_lock(&da1->mlock);
en_queue(da1->que);
pthread_mutex_unlock(&da1->mlock);
}
return (void*)da1;
}
void* fn_1(void* arg)
{
data* da2 = (data*)arg;
while (1)
{
end = time(NULL);
if (end == start + 180)
break;
pthread_mutex_lock(&da2->mlock);
//en_queue(da2->que);
de_queue(da2->que);
da2->count +=1;
pthread_mutex_unlock(&da2->mlock);
}
printf("count:%d\n",da2->count);
return (void*)da2;
}
int main()
{
mp = memorypool_create(sizeof(int),7,1);
pthread_t thread0;
pthread_t thread1;
data da;
da.count = 0;
pthread_mutex_init(&da.mlock, NULL);
da.que = queue_init();
pthread_create(&thread0, NULL, fn_0, (void*)&da);
pthread_create(&thread1, NULL, fn_1, (void*)&da);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
pthread_mutex_destroy(&da.mlock);
return 0;
}
四、遗留BUG的解决
2019/2/17:
在两个线程分别向内存池申请内存块、释放内存块到内存池时,出现了mp指针的指向错误,
经解决,是内存池在memory_creat和memory_free时,对p_memory->block指针赋值错误造成的。
该bug将在上面代码中标记出来。
犯这样的错误是因为没有搞清楚:1.地址+size,想得到地址,因注意size的进制、量度;
2.堆是从低地址开始分配的,栈是从高地址开始分配的。没有区分地址分配的方向。见下图。