线程

1、 多进程的优点:

可以执行多任务,进程之间切换频繁时,CPU效率比较低,进程间通信较复杂
多线程(同一个进程里面的多线程)
多线程可以实现多任务,并且通信较为简单

2、

不同的进程地址空间是独立的
同一个进程的不同线程共享地址空间(堆段、数据段、代码段),栈段是独立的
原来的进程可以创建一个新的线程,把原来的进程称为是主线程,新创建的线程称为是子线程

3、进程和线程的区别和联系

进程和线程都是动态的
进程和线程都可以实现并发任务
进程是分配资源的最小单位
线程是调度的最小单位

4、创建线程

int  pthread_create(pthread_ * threadID, const pehread_attr_t *attr, void * (* routine)(void *),void * arg);
功能:创建线程
参数:threadID:线程的编号
attr:线程属性,一般写成NULL
routine:函数指针,是线程执行函数
arg:传递给线程执行的函数的参数
返回值:成功为0,失败为-1
在编译线程相关的函数时,需要在gcc后面链接pthread库,例:gcc  thread.c  -lpthread
#include <stdio.h>
#include <pthread.h>


void * threadFunc(void * arg)
{
	printf("thread do something\r\n");
}

int main()
{
	pthread_t threadId;
	int ret = 0;

	ret = pthread_create(&threadId, NULL, threadFunc, NULL);
	if (ret < 0)
	{
		perror("create thread error");
		return -1;
	}

//	while(1)
//	{
		printf("main thread\r\n");
		sleep(1);
//	}
	
	return 0;
}
等待子线程退出
int  pthread_join(pthread_t threadID, void ** arg);
功能:等待子线程日退出
参数:threadID:要等待的线程的线程编号
arg : 子线程退出的状态
返回值:成功返回0,失败返回-1;
join一般放在主线程即将退出之前
#include <stdio.h>
#include <pthread.h>


void * threadFunc(void * arg)
{
	printf("thread do something\r\n");
	sleep(3);
}

int main()
{
	pthread_t threadId;
	int ret = 0;

	ret = pthread_create(&threadId, NULL, threadFunc, NULL);
	if (ret < 0)
	{
		perror("create thread error");
		return -1;
	}

//	while(1)
//	{
//	}
	pthread_join(threadId, NULL);
	printf("after join\r\n");	
	return 0;
}
线程退出
void pthread_exit (void * ptr);
功能:线程退出
参数:ptr线程退出时返回的值
注意:局部变量的地址不能返回,因此局部变量的地址不能作为pthread_exit 的参数
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

void * threadFunc(void * arg)
{
	//int i = 0;
	printf("thread do something\r\n");
	sleep(3);
	pthread_exit(&i);
	//exit(0);
	//return &i;
}

int main()
{
	pthread_t threadId;
	int ret = 0;

	ret = pthread_create(&threadId, NULL, threadFunc, NULL);
	if (ret < 0)
	{
		perror("create thread error");
		return -1;
	}

//	while(1)
//	{
//	}
	pthread_join(threadId, NULL);
	printf("after join\r\n");	
	return 0;
}

5、线程间同步

使用semaphore             PV原语

同步例如:ABABABABAB   交替执行
1、定义       sem_t  sem;
2、初始化   sem_init(&sem , 0 , value);        //value是一个非负整数
3、创建线程
4、在线程执行函数中,在合适的位置先进行p操作(减1)sem_wait  do  someThing,     v操作(加1)  sem_post(&sem)
5、在线程执行结束前,如果不再使用sem,需要将它销sem_destroy(&sem)
注:p操作sem_wait是一个阻塞函数
A线程V操作其他线程的sem
A线程中P-->semA     V-->semB
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

sem_t sem1;
sem_t sem2;

void * threadFunc1(void * arg)
{
	while(1)
	{
	sem_wait(&sem1);
		printf("hello!\r\n");
//		sleep(1);
	sem_post(&sem2);
	}
}

void * threadFunc2(void * arg)
{
	while(1)
	{
		sem_wait(&sem2);
		printf("welcome farsight!\r\n");
//		sleep(1);
		sem_post(&sem1);
	}
}

int main()
{
	pthread_t thid1;
	pthread_t thid2;

	int ret1 = 0;
	int ret2 = 0;

	sem_init(&sem1, 0, 1);
	sem_init(&sem2, 0, 0);
	ret1 = pthread_create(&thid1, NULL, threadFunc1, NULL);
	ret2 = pthread_create(&thid2, NULL, threadFunc2, NULL);
	if (ret1 < 0 || ret2 < 0)
	{
		perror("create thread error");
		return -1;
	}

	pthread_join(thid1, NULL);
	pthread_join(thid2, NULL);
	sem_destroy(&sem1);
	sem_destroy(&sem2);
	return 0;
}


6、线程互斥

mutex  保证线程执行的完整性
锁的分类(了解)
快速互斥锁
读写锁(银行)
条件锁

mutex使用(保证线程执行的完整性)
1、创建/定义mutex     pthread_mutex_t   mutex;
2、初始化锁        pthread_mutex_init(&mutex ,  NULL);
3、创建线程        pthread_create(&threadID, NULL, threadFunc, NULL);
4、在线程执行函数中,在合适的位置先上锁  pthread_mutex_lock(&mutex)
再执行功能do something,最后解锁  pthread_mutex_unlock(&mutex);
#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex;

void * threadFunc(void * arg)
{
	static char data[11] = {};
	int i = 0;
	char * p = (char * )arg;

pthread_mutex_lock(&mutex);
	for (i = 0; i < 10; i++)
	{
		data[i] = p[i];
		sleep(1);
	}
pthread_mutex_unlock(&mutex);
	printf("data=%s\n", data);
}

int main()
{
	char buf1[] = {"1234567890"};
	char buf2[] = {"abcdefghig"};

	pthread_t thid1;
	pthread_t thid2;

	int ret1 = -1;
	int ret2 = -1;
	
	pthread_mutex_init(&mutex, NULL);

	//create thread, and copy buf to own dataBuf
	ret1 = pthread_create(&thid1, NULL, threadFunc, buf1);
	ret2 = pthread_create(&thid2, NULL, threadFunc, buf2);

	if (ret1 < 0 || ret2 < 0)
	{
		perror("pthread create error");
		return -1;
	}

	pthread_join(thid1, NULL);
	pthread_join(thid2, NULL);
	
	pthread_mutex_destroy(&mutex);
	return 0;
}


5、线程执行结束,不再使用锁时,需要销毁锁

pthread_mutex_destroy(&mutex);

注:上锁 pthread_mutex_lock(&mutex)是阻塞函数
A线程上锁,只能由A线程进行解锁,其它线程没有权限解这个锁

可重入---每次执行都一样       不可重入---执行可能不一样

动态定义宏的方法
在编译的时候,给gcc加一个参数  -DXXXX     这里的XXXX是具体代码中用到的宏名
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值