线程的学习

线程的基础

进程和程序

进程是资源分配的基本单位

线程是执行的基本单位

进程和线程的关系

一个进程中可以有多个线程,最少有一个线程(主线程)

线程共享进程的资源,每个线程都有自己的属性。线程的id,线程自己的栈帧,自己的信号屏蔽字等。

进程的切换和进程的通信,消耗资源非常大,效率低下。

线程共享进程的资源,线程的切换和线程间的通信很灵活,消耗资源比较少,效率很好。

线程的创建,退出,分离,汇合

1.创建线程使用pthread_create(3)

 #include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,\

void *(*start_routine) (void *), void *arg);

举例:验证 一个进程中有多个线程。需要获取到进程的pid和线程的tid。

获取进程的pid ,使用getpid(2)

获取线程的tid,使用pthread_self(3)

pthread_t pthread_self(void);
功能:获取线程自己的id

2.线程的退出

return 和exit(3)的区别

在线程函数中调用return只是线程执行函数的结束。代表线程的结束。

如果在线程函数中调用exit(3) 将会终止整个进程,那么进程中的线程就会终止。切记,不要在线程执行函数中调用exit(3)等函数。

终止一个线程使用pthread_exit(3)

 #include <pthread.h>

 void pthread_exit(void *retval);

功能:终止当前线程

 #include <pthread.h>

int pthread_cancel(pthread_t thread);

线程的汇合和分离

线程创建以后,线程退出的时候,线程的资源自动回收,不需要主线程等待,这样的线程称为分离线程

线程创建以后,线程退出以后,需要其他线程回收线程的资源,这样的线程称为线程的汇合。

线程汇合使用pthread_join(3)完成。

  #include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

线程的分离使用pthread_detach(3)

 #include <pthread.h>

int pthread_detach(pthread_t thread);

举例说明:退出,回合

 

补充:void *(*start_routine) (void *)

 

线程对共享资源的访问

线程创建完毕,进程中所有的线程是异步的。

要保证线程函数的安全性,那么线程必须为可重入的。

举例,线程函数不是可重入函数的时候,对临界资源的访问,造成程序的乱序。

线程同步

多个线程对临界资源进程访问的时候,需要由异步变为同步。

posix线程中提供了三种方式

1.mutex锁

pthread_mutex_init(3)

 #include <pthread.h>

pthread_mutex_t   是mutex锁的类型  静态初始化一个mutex锁

       pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;

       pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

       pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

 int pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutex‐ attr_t *mutexattr);

 

int pthread_mutex_lock(pthread_mutex_t *mutex);

 

 int pthread_mutex_trylock(pthread_mutex_t *mutex);

 

 int pthread_mutex_unlock(pthread_mutex_t *mutex);

 

 int pthread_mutex_destroy(pthread_mutex_t *mutex);

使用mutex锁解决临界资源问题

2.条件变量

什么是条件变量?

线程间的同步:线程A需要等待某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中,使这个条件成立,然后线程A继续往下之执行,那么这个条件就是条件变量。

pthread库中通过使用pthread_cont_t类型来表示条件变量类型。

对这种类型的操作包括一下:

pthread_cond_init(3)

#include <pthread.h>

       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//静态初始化条件变量

 int    pthread_cond_init(pthread_cond_t    *cond,    pthread_condattr_t  *cond_attr);

 

int pthread_cond_signal(pthread_cond_t *cond);

 

 int pthread_cond_broadcast(pthread_cond_t *cond);

 

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

 

 int   pthread_cond_timedwait(pthread_cond_t   *cond,    pthread_mutex_t
       *mutex, const struct timespec *abstime);

 

int pthread_cond_destroy(pthread_cond_t *cond);

(1) 先解mutex锁

(2)等待signal的到来

(3)重新加mutex锁

生产者和消费者的问题

需要使用到链表。生产出来的节点串到链表的头部。消费者从链表的头部取走一个节点进行消费。

如果链表中没有节点的时候,消费者一直等待生产者生产。

 

 

3.信号量

对多个资源的共享使用信号量,想使用其中的一个资源的时候,首先判断是否有可用资源。如果有,是资源的可用数量减1.如果没有可用资源,线程等待其他线程释放资源。当线程释放资源的时候,资源可用数量加1.

信号量是一个类型  sem_t

关于信号量的操作,系统提供了一下函数  sem_init(3)

  #include <semaphore.h>

 int sem_init(sem_t *sem, int pshared, unsigned int value);

0  成功   -1  错误  errno被设置

sem_destroy(3)

 #include <semaphore.h>

int sem_destroy(sem_t *sem);

sem_post(3)

  #include <semaphore.h>

int sem_post(sem_t *sem);

sem_wait(3)

 #include <semaphore.h>

int sem_wait(sem_t *sem);

 int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

举例使用信号量完成生产者和消费者模型

使用循环队列完成,队列固定大小

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值