Linux线程

线程

  • 一个程序中的一个执行流,是一个进程内部的控制序列
  • 调度的基本单位
  • 每个进程都至少有一个线程
    进程和线程的区别
    1.进程是内核分配资源的基本单位、线程是调度的基本单位
    2.线程在进程地址空间运行,线程执行流比进程更小
    3.线程之间大部分共享数据,但也有自己的部分数据:线程ID、寄存器、栈、errno、信号屏蔽字、调度优先级
    4.线程的创建/切换比进程轻量化
    5.由于进程之间相互独立,而线程相互共享资源,因为进程更安全,线程更方便
    这里写图片描述
    由上图可知,线程在进程的虚拟地址空间上运行,共有堆栈上的数据(定义的函数、定义的全局变量)
    线程的优点
  • 创建一个新线程的代价比创建一个新进程小得多
  • 能充分利用多处理器的并行数量
  • 在等待慢速I/O操作结束时,程序可执行其他的计算任务
  • 占用的资源少,切换成本低
    线程的缺点

  • 健壮性降低:共享资源可能会造成不良的影响,线程之间缺乏保护

  • 缺乏访问控制:如果一个线程调用某个OS函数会对整个进程造成影响
  • 性能损失:一个被外部事件阻塞的计算密集型线程往往无法与其他线程共享一个处理器,如果此时计算密集型线程的数量比可用的处理器多,可能调度效率降低

线程控制

创建线程

int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void* (*start_rtn)(void*),void *restrict arg);

返回值:若成功,返回0;若失败,返回错误编号
当pthread_create成功返回后。新创建的线程ID会被设置成tidp指向的内存单元,attr参数用于定制不同的线程属性
新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。

线程等待

为什么需要线程等待?

1.已经退出的线程,其空间还没有释放,仍在进程的地址空间
2.创建新的线程不会复用刚刚退出线程的地址空间

int pthread_join(pthread_t thread,void **rval_ptr)

返回值:若成功,返回0;否则,返回错误编号
以阻塞的方式等待thread指定的线程结束,当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回
如果对线程的返回值不感兴趣,可以把rval_ptr设置成NULL,在这种情况下,调用pthread_join函数可以等待指定的线程终止,但不获取线程的终止状态。

分离线程

int pthread_datach(pthread_t tid)

返回值:若成功,返回0;否则返回错误编号
由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码
pthread_detach(pthread_self())
或者父线程调用
pthread_detach(thread_id)(非阻塞,可立即返回)
这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。

线程终止

void pthread_exit(void *value_ptr)

参数value_ptr不要指向一个局部变量
返回值:无返回值,和进程一样,线程结束后无法返回到调用者
注:pthread_exit和return返回的指针所指向的内存单元之能是全局的或者malloc开辟的堆空间,不能在线程函数的栈上分配,当其他线程得到这个返回值时,线程函数栈帧已经退出。

int pthread_cancel(pthread_t thread)

参数thread:线程ID
返回值:成功返回0,否则返回错误码

线程的同步和互斥

1.mutex互斥量
互斥量本质上是一把锁,在访问共享资源前对互斥量进行设置加锁,在访问完成后释放(解锁)互斥量。

  • 大部分情况下,线程都使用的局部变量,这些变量存储在线程独自的线程栈中,这种情况,变量属于单个线程,其他线程不能访问
  • 有时候许多变量需要线程间共享,这样的变量称为共享变量,可以通过数据的共享,完成多个线程间的交互
  • 多个线程并发操作共享变量,会带来一些问题

互斥量的接口

初始化互斥量

int pthread_mutex_init(pthread_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

返回值:若成功返回0,否则返回错误编号
参数:mutex要初始化的互斥量,attr:NULL

销毁互斥量
注意:不要销毁一个已经加锁的互斥量,已经销毁的互斥量,确保后面的线程不会尝试加锁

int pthread_mutex_destroy(pthread_mutex *mutex)

互斥量加锁和解锁

int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
成功返回0,否则返回错误码

调用pthread_lock可能遇到下面情况

互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功
发起函数的调用,其他线程已经将该锁住该互斥量,那么pthread_lock
将会进入堵塞,等待互斥量解锁。

条件变量

  • 当一个线程互斥的访问某个变量时,他可能发现在去其他线程改变之前,什么都做不了。

条件变量是线程可用的另一种同步机制,条件变量给多个线程提供了一个汇合的场所,条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生
条件变量本身是由互斥量保护的,线程在改变条件状态下必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为互斥量在锁定后才能计算条件

条件变量函数

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_cond_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

两个函数返回值:若成功返回0,否则返回错误编号

等待条件满足:

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex)
int pthread_cond_timewait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr)

两个函数的返回值成功返回0,否则返回错误编码
timewait函数比wait多了一个超时,超时值制定了我们愿意等待多久,它是通过timespec结构体来指定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值