线程

一、线程是什么

linux下:线程是轻量级进程。(linux下线程和进程并不做明显的区别。线程是PCB进行模拟的.进程的一个执行流)

               进程是具有多个线程的线程组。

进程与线程的对比

1.进程是操作系统分配资源的一个基本单位。

线程是操作系统CPU调度的一个基本单位。

2.进程是拥有一个完整的资源平台。每个线程除了共享资源外也拥有自己的部分数据:线程ID,一组寄存器(保存上下文(一个进        程内容切换到另一个进程内容)数据),栈(防止调用栈混乱),errno(错误码),信号屏蔽字,调度优先级。

3.线程会共享进程所分配的资源:文件描述符,每种信号的处理方式 ,当前的工作目录,用户ID和组ID,同一虚拟地址空间。

线程的优点:

线程能减少并发执行的时间和空间开销

时间上:线程比同一进程的创建时间、终止时间、进程内的线程cancel切换时间都短。

空间上:统一进程的各线程间共享资源和文件资源,可以不通过内核直接通信。

线程的缺点:

缺乏访问控制,健壮性降低,编程难度提高,性能损失

主线程:

1.线程组内的第一个线程,在用户态被称为主线程(main thread),在内核被称为group leader

2.线程组的ID就是第一个线程的ID.group_leader指针则指向自身,即就是主线程的进程

描述符。所以线程组内存在一个线程ID==进程ID,该线程就为线程组的主线程。

线程组tgid = 主线程pid

二、线程控制

头文件:<pthread.h>

链接函数时要使用编译器命令的“-lpthread”选项。

创建一个线程:

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void*),void *arg)

thread:返回线程ID

attr:设置线程属性,为NULL时表示默认属性

start_routine:线程的入口函数,线程启动后要执行的函数

arg:传给启动函数的参数

返回值:成功返回0,失败返回错误码(非0值)。

    void  *thr_start(void *arg)
  {    
       while(1){
           printf("thread:%p calling!!\n",(uint64_t*)pthread_self());
          sleep(1);
      }
      return NULL;
 } 
  int main()
  {
      pthread_t tid;
      //pthread_create创建线程,线程入口地址为thr_start
      int ret=pthread_create(&tid,NULL,thr_start,NULL);
      if(ret!=0){
          printf("pthread_create perror\n");
          return -1;
      }
      while(1){
      printf("thread %p playing game!!\n",(uint64_t*)pthread_self());
      sleep(1);
      } 
      return 0;
  }

线程终止:

1.从线程函数return(这种方法对主线程不适用,从main函数return相当于调用exit)。

2.线程调用pthread_exit 来终止自己(谁调用谁退出)。

void pthread_exit (void *value_ptr)

value_ptr :不要指向一个局部变量。

返回值:无返回值,跟进程一样。

3.线程调用pthread_cancel 终止同一进程中的另一个线程(即一个进程可以被另一个进程

取消)。

int pthread_cancel (pthread_t thread)

thread :线程ID

返回值:成功返回0,失败返回错误码

线程等待:

功能:挂起等待,直到id为thread的线程终止。(不会自动释放空间)

int pthread_join (pthread_t thread,void **value_ptr)

thread:线程ID.

value_ptr:指向一个指针,后者指向线程的返回值。

返回值:成功返回0,失败返回错误码

线程分离:(自动释放线程资源)

int pthread_detach(pthread_t thread)

分离可以是线程组内其他线程对目标线程进行分离,也可以是先称自己分离:

pthread_detach(pthread_self());

等待join和分离是冲突的,一个线程不能既是joinable又是分离的。

返回值 :1.线程可以通过return和pthread_exit传递退出返回值

               2.如果线程被取消,这个线程的返回值是 -1 PTHREAD_CANCELED

               3.线程退出后,如果是joinable状态,则不会自动释放资源,需要其他线程使用

pthread_join接口来等待线程退出后,并获取返回值,释放资源,否则资源无法释放将造成资源泄露。当线程被分离之后,那么这个线程退出时候,自动释放资源不需要被等待。当一个线程被分离之后,那么这个线程是无法被pthread_join等待否则返回EINVAL错误。

三、互斥量

同步:可控时序性 互斥:同一时间的唯一访问性

互斥锁:同一时间的唯一访问性

互斥锁类型: pthread_mutex_t

互斥量的初始化:pthread_mutex_init (&mutex,&attr)

     int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict *attr)

       mutex:要初始化的互斥量

       attr:NULL

      pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER (不用销毁)

互斥量的加锁:

      int pthread_mutex_lock(pthread_mutex_t *mutex)

互斥量的解锁:(任何一个退出的地方)

         int pthread_mutex_unlock(pthread_mutex_t *mutex)

互斥量的销毁: 

          int pthread_mutex_destroy(pthread_mutex_t *mutex)

四、产生死锁的四个必要条件:

1.互斥条件

2.不可剥夺条件(我自己拥有的资源,不能被别人夺走)

3.请求与保持条件(拥有一个资源,再继续请求另一个资源)

4.环路等待条件(彼此互相等待)

死锁的处理:避免死锁----银行家算法

                     检测死锁---资源分配图简化算法

                      预防死锁----资源有序分配法

同步,互斥的目的:保持安全

同步:可控时序性。 互斥:同一时间的唯一访问性

加锁:在访问临界资源之前        解锁:在每一个线程的退出地方

五、条件变量

生产者--消费者模型:

三种关系:生产者--生产者 (互斥)

                   消费者--消费者(互斥)

                  生产者--消费者 (同步,互斥)

两个角色:生产者,消费者

一种机制:互斥机制

初始化:

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

    cond :要初始化的条件变量

     attr :NULL

销毁:

int pthread_cond_destroy (pthread_cond_t *cond)

等待条件满足:(包括解锁和休眠操作,两个都是原子操作,不能被打断)

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

  cond :要在这个条件变量上等待

   mutex :互斥量

唤醒等待: 唤醒等待在这个条件变量上的线程

      int pthread_cond_broadcast (pthread_cond_t *cond);

      int pthread_cond_signal (pthread_cond_t *cond);

 

六、POSIX信号量

(头文件:#include<semaphore.h>)

和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。只不过POSIX可以用于线程间同步。

信号量也可以实现同步和互斥。

初始化信号量(一次只能初始化一个):

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

      pshared : 0 表示线程间共享 非零表示进程间共享

       value :信号量初值

销毁信号量:

       int sem_destroy(sem_t *sem)

等待信号量:

      int sem_wait(sem_t *sem)

功能:等待信号量,会将信号量的值减1(相当于p操作)

发布信号量:

int sem_post(sem_t *sem)

功能:发布信号量,表示资源使用完毕,可以归还资源了,将信号量加1(相当于v操作)

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值