linux下线程使用

什么是线程

线程,是进程内部的一个控制序列。
即使不使用线程,进程内部也有一个执行线程。

为什么要使用多线程

使用fork创建进程以执行新的任务,该方式的代价很高。
多个进程间不会直接共享内存
线程是进程的基本执行单元,一个进程的所有任务都在线程中执行,进程要想执行任务,必须得有线程,进程至少要有一条线程,程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程

线程的优点缺点

线程的优点、缺点
优点: 创建线程比创建进程,开销要小。
缺点: 1)多线程编程,需特别小心,很容易发生错误。
2)多线程调试很困难。
3)把一个任务划分为两部分,
用两个线程在单处理器上运行时,不一定更快。
除非能确定这两个部分能同时执行、且运行在多处理器上.

线程的应用场合

  1. 需要让用户感觉在同时做多件事情时,
    比如,处理文档的进程,一个线程处理用户编辑,一个线程同时统计用户的字数。

  2. 当一个应用程序,需要同时处理输入、计算、输出时,
    可开3个线程,分别处理输入、计算、输出。
    让用户感觉不到等待。

  3. 高并发编程。

线程的使用

1)线程的创建
pthread_create
原型:int pthread_create (
pthread_t *thread,
pthread_attr_t *attr,
void *(start_routine)(void),
void *arg);

参数:thread, 指向新线程的标识符。
通过该指针返回所创建线程的标识符。
attr, 用来设置新线程的属性。
一般取默认属性,即该参数取NULL
start_routine, 该线程的处理函数
该函数的返回类型和参数类型都是void*
arg, 线程处理函数start_routine的参数

功能:创建一个新线程,
同时指定该线程的属性、执行函数、执行函数的参数
通过参数1返回该线程的标识符。

返回值:成功,返回0
失败,返回错误代码
注意:大部分pthread_开头的函数成功时返回0,失败时返回错误码(而不是-1)

注意:使用fork创建进程后,进程马上就启动,但是是和父进程同时执行fork后
的代码。
使用pthread_create创建线程后,新线程马上就启动,即执行对应的线程处理函数。

2)线程的终止
pthread_exit
原型:void pthread_exit (void *retval)
功能:在线程函数内部调用该函数。
终止该线程,并通过参数retval返回一个指针。
该指针不能指向该线程的局部变量。

3)等待指定线程结束
pthread_join
功能:类似与进程中的waitpid
等待指定的线程结束,并使参数指向该线程函数的返回值(用pthread_exit返回的值)
原型:int pthread_join (pthread_t th,
void ** thread_return);
参数:th, 指定等待的线程
thread_return, 指向该线程函数的返回值
线程函数的返回值类型为void*,故该参数的类型为void**

4)使用线程程序的编译
(1) 编译时,定义宏_REENTRANT
即: gcc -D_REENTRANT (#define REENTRANT)

功能:告诉编译器,编译时需要可重入功能。
即使得,在编译时,编译部分函数的可重入版本。

注:在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临界资源,很容易造成调用函数处理结果的相互影响,如果一个函数在多线程并发的环境中每次被调用产生的结果是不确定的,我们就说这个函数是"不可重入的"/"线程不安全"的。

(2) 编译时,指定线程库
即: gcc -lpthread
功能:使用系统默认的NPTL线程库,
即在默认路径中寻找库文件libpthread.so
默认路径为/usr/lib和/usr/local/lib

当系统默认使用的不是NPTL线程库时(系统较老,2003年以前)
指定:gcc -L/usr/lib/nptl -lpthread
补充: -L 指定库文件所在的目录
-l 指定库文件的名称(-lpthread ,指库文件名为libpthread.so)

总结:一般使用如下形式即可
gcc -D_REENTRANT -lpthread mythread.c -o mythread

线程的使用

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

int my_global;

void* my_thread_handle(void *arg) 
{
	int val;

	val = *((int*)arg);

	printf("new thread begin, arg=%d\n", val);
	my_global += val;

	sleep(3);

	pthread_exit(&my_global);

	//  不再执行
	printf("new thread end\n");
}

int main(void)
{
	pthread_t  mythread;
	int arg;
	int ret;
	void *thread_return;

	arg = 100;
	my_global = 1000;

	printf("my_global=%d\n", my_global);
	printf("ready create thread...\n");
	
	ret = pthread_create(&mythread, 0, my_thread_handle, &arg);
	if (ret != 0) {
		printf("create thread failed!\n");
		exit(1);
	}

	printf("wait thread finished...\n");
	ret = pthread_join(mythread, &thread_return);
	if (ret != 0) {
		printf("pthread_join failed!\n");
		exit(1);
	}
	printf("wait thread end, return value is %d\n", *((int*)thread_return));
	printf("my_global=%d\n", my_global);

	printf("create thread finished!\n");
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值