这文章极好的介绍了互斥锁和多线程的基础(半小时可看完)
https://www.ibm.com/developerworks/cn/linux/thread/posix_thread1/index.html
https://www.ibm.com/developerworks/cn/linux/thread/posix_thread2/index.html
https://www.ibm.com/developerworks/cn/linux/thread/posix_thread3/index.html
这文章介绍了互斥锁和条件变量的基础,和实例(分分钟看完)
https://blog.csdn.net/qq_39736982/article/details/82380689
关键在于实例实践过程中出现的问题
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//节点结构体
struct msg
{
int num; //数据区
struct msg *next; //链表区
};
struct msg *head = NULL;//头指针
struct msg *mp = NULL; //节点指针
//利用宏定义的方式初始化全局的互斥锁和条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
void *producter(void *arg)
{
while (1)
{
mp = malloc(sizeof(struct msg));
//if(mp == NULL)
//printf("malloc error\n");
//else
//printf("---mp malloc = %p\n" , mp);
mp->num = rand() % 400 + 1;
printf("---producted---%d\n", mp->num);
pthread_mutex_lock(&mutex);//访问共享区域必须加锁
mp->next = head;
head = mp;
//mp->next = head;
//mp = head;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&has_product);//通知消费者来消费
//sleep(1);
//srand(time(0));
sleep(rand() % 3);
}
return NULL;
}
void *consumer(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);//访问共享区域必须加锁
while (head == NULL)//如果共享区域没有数据,则解锁并等待条件变量
{
pthread_cond_wait(&has_product, &mutex);
}
mp = head;
head = mp->next;
pthread_mutex_unlock(&mutex);
printf("------------------consumer--%d\n", mp->num);
free(mp); //释放被删除的节点内存
//printf("------------------mpfree = %p\n" , mp);
mp = NULL;//并将删除的节点指针指向NULL,防止野指针
//sleep(1);
//srand(time(0));
sleep(rand() % 3);
}
return NULL;
}
int main(void)
{
pthread_t ptid, ctid;
//创建生产者和消费者线程
pthread_create(&ptid, NULL, producter, NULL);
pthread_create(&ctid, NULL, consumer, NULL);
//主线程回收两个子线程
pthread_join(ptid, NULL);
pthread_join(ctid, NULL);
return 0;
}
该代码重点有三:
1.链表的初始化和插入,头插法,尾插法
2.互斥锁的使用,多线程访问相同变量时,要使用锁
3.条件变量的使用,等待条件变量时会自动解锁
该代码的问题,建议先实践再分析
问题在于free的内存会马上给malloc使用,如果打印了mp的地址才会发现这个问题。所以如果不把内存的申请和释放也锁住,会导致两个线程同时操作内存,引起内存问题。