Linux多线程实现及线程同步函数分析
在Linux中,多线程的本质仍是进程,它与进程的区别:
进程:独立地址空间,拥有PCB
线程:也有PCB,但没有独立的地址空间(共享)
线程的特点:
1,线程是轻量级进程,有PCB,创建线程使用的底层函数和进程一样,都是clone
2,从内核看进程和线程是一样的,都有各自不同的PCB
3,进程可以蜕变成线程
4,在LINUX中,线程是最小的执行单位,进程是最小的分配资源单位
查看指定线程的LWP号命令:
ps -Lf pid
线程优点:
提高程序并发性
开销小
数据通信,共享数据方便
线程缺点:
库函数 ,不稳定
调试,编写困难,GDB
对信号支持不好
线程属性,可以在一开始就设置好分离态,具体在下面的代码有说明!
线程同步,主要有互斥锁mutex,读写锁,条件变量,信号量
线程创建函数原型:
int pthread_create(
    pthread_t *thread,  				// 线程ID
    const pthread_attr_t *attr, 		// 线程属性
    void *(*start_routine) (void *), 	// 线程主函数
    void *arg							// 主函数参数
);
粘上基本创建线程模型:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
//函数回调
void *mythread(void *args)
{
	printf("child thread id==[%ld]\n", pthread_self());
}
int main()
{
	pthread_t thread;
	
	//创建一个线程
	int ret = pthread_create(&thread, NULL, mythread, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret)); 
		return -1;
	}
	printf("main thread id==[%ld]\n", pthread_self());
	sleep(1);
}
线程属性,在创建时分离代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
void *mythread(void *args)
{
	printf("child thread id==[%ld]\n", pthread_self());
}
int main()
{
	pthread_t thread;
	//线程属性
	pthread_attr_t attr;
	//线程属性初始化
	pthread_attr_init(&attr);
	//设置线程到分离属性
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	
	//创建一个线程
	int ret = pthread_create(&thread, &attr, mythread, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret)); 
		return -1;
	}
	printf("main thread id==[%ld]\n", pthread_self());
	sleep(1);
	
	ret = pthread_join(thread, NULL);
	if(ret!=0)
	{
		printf("pthread_join error, [%s]\n", strerror(ret));
	}
	//释放线程属性
	pthread_attr_destroy(&attr);
	return 0;
}
互斥锁实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
//定义一把锁
pthread_mutex_t mutex;
void *mythread1(void *args)
{
	while(1)
	{
		//加锁
		pthread_mutex_lock(&mutex);
		pthread_mutex_lock(&mutex);
		printf("hello ");
		sleep(rand()%3);
		printf("world\n");
	
		//解锁
		pthread_mutex_unlock(&mutex);
		sleep(rand()%3);
	}
	pthread_exit(NULL);
}
void *mythread2(void *args)
{
	while(1)
	{
		//加锁
		pthread_mutex_lock(&mutex);
		printf("HELLO ");
		sleep(rand()%3);
		printf("WORLD\n");
		//解锁
		pthread_mutex_unlock(&mutex);
		sleep(rand()%3);
	}
	pthread_exit(NULL);
}
int main()
{
	int ret;
	pthread_t thread1;
	pthread_t thread2;
	//随机数种子
	srand(time(NULL));
	
	//互斥锁初始化
	pthread_mutex_init(&mutex, NULL);
	ret = pthread_create(&thread1, NULL, mythread1, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	
	ret = pthread_create(&thread2, NULL, mythread2, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	//等待线程结束
	pthread_join(thread1, NULL);
	pthread_join(thread2, NULL);
	//释放互斥锁
	pthread_mutex_destroy(&mutex);
	return 0;
}
读写锁代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
int number = 0;
//定义一把读写锁
pthread_rwlock_t rwlock;
void *fun_write(void *args)
{
	int i = *(int *)args;
	int n;
	while(1)
	{
		//加写锁
		pthread_rwlock_wrlock(&rwlock);
		n = number;
		n++;
		//sleep(rand()%3);
		number = n;		
		printf("W->[%d]:[%d]\n", i, number);
		//解写锁
		pthread_rwlock_unlock(&rwlock);
		sleep(rand()%3);
	}
	pthread_exit(NULL);
}
void *fun_read(void *args)
{
	int i = *(int *)args;
	while(1)
	{
		//加读锁
		pthread_rwlock_rdlock(&rwlock);
		printf("R->[%d]:[%d]\n", i, number);	
		//解锁
		pthread_rwlock_unlock(&rwlock);
		sleep(rand()%3);
	}
	pthread_exit(NULL);
}
int main()
{
	int i;
	int ret;
	int n = 8;
	int arr[8];
	pthread_t thread[8];
	//读写锁初始化
	pthread_rwlock_init(&rwlock, NULL);
	//创建3个写线程
	for(i=0; i<3; i++)
	{
		arr[i] = i;
		ret = pthread_create(&thread[i], NULL, fun_write, (void *)&arr[i]);
		if(ret!=0)
		{
			printf("pthread_create error, [%s]\n", strerror(ret));
			return -1;
		}
	}
	
	//创建5个读线程
	for(i=3; i<n; i++)
	{
		arr[i] = i;
		ret = pthread_create(&thread[i], NULL, fun_read, (void *)&arr[i]);
		if(ret!=0)
		{
			printf("pthread_create error, [%s]\n", strerror(ret));
			return -1;
		}
	}
	for(i=0; i<n; i++)
	{
		//回收子线程
		pthread_join(thread[i], NULL);
	}
	//释放读写锁资源
	pthread_rwlock_destroy(&rwlock);
	return 0;
}
cond条件变量代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
typedef struct node
{
	int data;
	struct node *next;
}NODE;
//链表头节点指针
NODE *head = NULL;
//互斥锁
pthread_mutex_t mutex;
//条件变量
pthread_cond_t cond;
//生产者线程处理函数
void *producer(void *args)
{
	NODE *pNode = NULL;	
	while(1)
	{
		pNode = (NODE *)malloc(sizeof(NODE));		
		if(pNode==NULL)
		{
			perror("malloc error\n");
			exit(1);
		}
		pNode->data = rand()%1000;
		//lock共享资源 
		pthread_mutex_lock(&mutex);
		pNode->next = head;
		head=pNode;
		printf("P:[%d]\n", head->data);
		
		//对共享资源解锁
		pthread_mutex_unlock(&mutex);
		
		//使用条件变量解除对线程到阻塞
		pthread_cond_signal(&cond);
		
		sleep(rand()%3);	
	}
}
//消费者线程处理函数
void *consumer(void *args)
{
	NODE *pNode = NULL;
	while(1)
	{
		//lock共享资源 
		pthread_mutex_lock(&mutex);
		if(head==NULL)
		{
			//条件不满足阻塞等待head不为空
			pthread_cond_wait(&cond, &mutex);
		}
		printf("C:[%d]\n", head->data);	
		pNode = head;
		head = head->next;
		//对共享资源解锁
		pthread_mutex_unlock(&mutex);
		free(pNode);
		pNode = NULL;
		sleep(rand()%3);	
	}
}
int main(int argc, char *argv[])
{
	int ret;
	pthread_t thread1;
	pthread_t thread2;
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	//初始化互斥锁
	pthread_mutex_init(&mutex, NULL);
	//初始化条件变量
	pthread_cond_init(&cond, NULL);
	//创建生产者线程
	ret = pthread_create(&thread1, NULL, producer, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	//创建消费者线程
	ret = pthread_create(&thread2, NULL, consumer, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	//主线程回收子线程
	pthread_join(thread1, NULL);	
	pthread_join(thread2, NULL);	
	//释放锁资源
	pthread_mutex_destroy(&mutex);
	//释放条件变量资源
	pthread_cond_destroy(&cond);
	return 0;
}
信号量,经典消费者生产者模型:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
typedef struct node
{
	int data;
	struct node *next;
}NODE;
//链表头节点指针
NODE *head = NULL;
sem_t sem_consumer;
sem_t sem_producer;
//生产者线程处理函数
void *producer(void *args)
{
	NODE *pNode = NULL;	
	while(1)
	{
		pNode = (NODE *)malloc(sizeof(NODE));		
		if(pNode==NULL)
		{
			perror("malloc error\n");
			exit(1);
		}
		pNode->data = rand()%1000;
		//sem_producer--, 若为0则阻塞
		sem_wait(&sem_producer);
		pNode->next = head;
		head=pNode;
		printf("P:[%d]\n", head->data);
		
		//sem_consumer++
		sem_post(&sem_consumer);
		sleep(rand()%3);	
	}
}
//消费者线程处理函数
void *consumer(void *args)
{
	NODE *pNode = NULL;
	while(1)
	{
		//sem_consumer--, 若为0则阻塞
		sem_wait(&sem_consumer);
		
		printf("C:[%d]\n", head->data);	
		pNode = head;
		head = head->next;
		//sem_producer++
		sem_post(&sem_producer);
		free(pNode);
		pNode = NULL;
		sleep(rand()%3);	
	}
}
int main(int argc, char *argv[])
{
	int ret;
	pthread_t thread1;
	pthread_t thread2;
	//信号量初始化
	sem_init(&sem_producer, 0, 5);
	sem_init(&sem_consumer, 0, 0);
	//创建生产者线程
	ret = pthread_create(&thread1, NULL, producer, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	//创建消费者线程
	ret = pthread_create(&thread2, NULL, consumer, NULL);
	if(ret!=0)
	{
		printf("pthread_create error, [%s]\n", strerror(ret));
		return -1;
	}
	//主线程回收子线程
	pthread_join(thread1, NULL);	
	pthread_join(thread2, NULL);	
	//释放信号量资源
	sem_destroy(&sem_producer);
	sem_destroy(&sem_consumer);
	return 0;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号