多线程程序设计

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属于一个进程的其他的线程共享进程拥有的全部资源。

       

Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。
 
Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。
 
进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间
 


1、线程的创建

#include <pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
参数说明:
thread:指向pthread_t类型的指针,用于引用新创建的线程。
attr:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL。
*(*start_routine)(void *):传递新线程所要执行的函数地址。
arg:新线程所要执行的函数的参数。
调用如果成功,则返回值是0,如果失败则返回错误代码。
 
与创建进程不同,创建线程时可以指定一个工作函数,新线程将从这个函数开始执行,函数返回也就等价于线程退出。
工作函数必须有一个(void *)型参数,新线程开始执行时,这个参数的值就是pthread_create函数的arg参数的值,因此可以利用它来向线程传递数据。
工作函数必须有(void *)型的返回值,它代表线程的退出状态。

 

#include <stdio.h>
#include <pthread.h>

void *thread_run(void* a)
{
	while (1)
	{
		sleep(1);
		printf ("线程 函数\n");
	}
}

int main()
{
	pthread_t thread_id;
	
	 int ret = pthread_create(&thread_id, NULL, thread_run, NULL);
	 if (ret != 0)
	 {
		perror ("pthread_create");
	
		return -1;
	 }
	
	while (1)
	{
		sleep(1);
		printf ("main 函数\n");
	}
	
	return 0;
}

2、线程的参数传递


#include <stdio.h>
#include <pthread.h>

struct data
{
	int a;
	int b;
};

void *thread_run(void* a)
{
	struct data *value = (struct data*)a; 
	
	printf ("线程接收到参数: %d, %d\n", value->a, value->b);
	
	int ret = value->a + value->b;
	
	// 不能通过 pthread_exit 返回栈上变量的地址
	pthread_exit((void*)ret);
	// pthread_exit((void*)&ret);
}

pthread_t func()
{
	struct data value;
	value.a = 10;
	value.b = 20;
	
	pthread_t thread_id;
	// 给线程传参要注意 栈上的变量的生命周期
	int ret = pthread_create(&thread_id, NULL, thread_run, (void *)&value);
	if (ret != 0)
	{
		perror ("pthread_create");

		return -1;
	}
	
	return thread_id;
}


int main()
{
	
	int *result;
	
	
	pthread_t thread_id = func();
	printf ("等待线程结束\n");
	pthread_join(thread_id, (void **)&result);
	
	printf ("result = %d\n", *result);

	return 0;
}

3、线程ID的获取

include <pthread.h>
pthread_t pthread_self(void);
返回当前线程的ID
 
可以使用pthread_equal()函数检查两个线程ID是否相同
include <pthread.h>
int pthread_equal(pthread_t t1, pthread_t t2);
如果想相等则返回0  


4、线程终止
 #include <pthread.h>
void pthread_exit(void *retval);
参数说明:
retval:返回指针,指向线程向要返回的某个对象。
线程通过调用pthread_exit函数终止执行,并返回一个指向某对象的指针。注意:绝不能用它返回一个指向局部变量的指针,因为线程调用结束后,这个局部变量就不存在了,这将引起严重的程序漏洞。
 
调用pthread_exit()等价于在工作函数中执行return,区别是pthread_exit()可以在工作函数调用的任何函数中被调用。
如果主线程调用pthread_exit(),而不是exit()或执行return,则其他线程将继续执行。

 

5、线程等待和线程分离

#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
参数说明:
th:将要等待的线程,线程通过pthread_create返回的标识符来指定。
thread_return:一个指针,指向另一个指针,而后者指向线程的返回值。不需要返回值则为NULL。
 #include <pthread.h>
int pthread_detach(pthread_t thread);
成功返回0。失败返回错误值
   
一个线程可以使用下面的方式分离自己:
   pthread_detach(pthread_self());
    pthread_detach()不会导致调用者阻塞,也不会导致所操作的线程结束。如果调用pthread_detach()时线程已经结束,则清理其所占用的资源。
 
对于创建时处于未分离状态的线程,必须调用一次pthread_join()或pthread_detach(),否则线程结束后就会留下没有释放的资源。    
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值