C语言-多线程与内存池、多线程与队列、多线程与内存池与队列的结合使用

一、多线程与内存池的结合使用:

一个线程memorymalloc,另一个线程memoryfree,效率是malloc\free的1.3倍(单线程时是3倍,本来双线程应该是6倍,但因为使用了线程的同步,使线程地并发变为了串行,故效率也应是3倍,又线程切换时会遇到阻塞的情况、再加上切换时的消耗,最后得到1.3)

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include "memorypool.h"
#include <time.h>

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 <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#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 <stdlib.h>
#include <string.h>
#include <stdio.h>


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 <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#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.堆是从低地址开始分配的,栈是从高地址开始分配的。没有区分地址分配的方向。见下图。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值