初始化条件变量

  1. int pthread_cond_init(pthread_cond_t *cv,pthread_cond_attr *cattr);
  2. 函数返回值:返回0表示成功,返回其他表示失败。
  3. 参数: pthread_cond_attr是用来设置pthread_cond_t的属性,当传入的值是NULL的时候表示使用默认的属性。

函数返回时,创建的条件变量保存在cv所指向的内存中,可以用宏PTHREAD_COND_INITIALIZER来初始化条件变量。值得注意的是不能使用多个线程初始化同一个条件变量,当一个线程要使用条件变量的时候确保它是未被使用的。

条件变量的销毁

  1. int pthread_cond_destroy(pthread_cond_t *cv);
  2. 返回值:返回0表示成功,返回其他值表示失败。

条件变量的使用:

  1. int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex)
  2. int pthread_cond_signal(pthread_cond_t *cv);

使用方式如下:

  1. pthread_mutex_lock(&mutex)
  2. while or if(线程执行的条件是否成立)
  3. pthread_cond_wait(&cond,&mutex);
  4. 线程执行
  5. pthread_mutex_unlock(&mutex);

为什么要加锁

  1. 线程在执行的部分访问的是进程的资源,有可能多个线程需要访问它,为了避免由于线程并发执行所引起的资源竞争,所以要让每个线程互斥的访问公共资源。
  2. 如果while或if判断不满足线程的执行条件时,线程回调用pthread_cond_wait阻塞自己。pthread_cond_wait被调用线程阻塞的时候,pthread_cond_wait会自动释放互斥锁。线程从调用pthread_cond_wait到操作系统把他放在线程等待队列之后的时候释放互斥锁。

使用while和if判断线程执行条件释放成立的区别。

在多线程资源竞争的时候,在一个使用资源的线程里面(消费者)判断资源是否可用,不可用便调用pthread_cond_wait,在另一个线程里面(生产者)如果判断资源可用的话,则会调用pthead_cond_signal发送一个资源可用的信号。

但是在wait成功之后,资源就不一定可以被使用,因为同时有两个或两个以上的线程正在等待次资源,wait返回后,资源可能已经被使用了,在这种情况下

  1. while(resource == FALSE)
  2. pthread_cond_wait(&cond,&mutex);

如果之后只有一个消费者,就可使用if。

分解pthread_cond_wait动作为以下步骤:

  1. 线程放在等待队列上,解锁
  2. 等待pthread_cond_signal或者pthread_cond_broadcast信号之后去竞争锁
  3. 若竞争到互斥锁则加锁

有可能多个线程在等待这个资源可用的信号,信号发出去之后只有一个资源可用,但是有A,B两个线程在等待,B速度比较快,获得互斥锁,然后加锁,消耗资源,然后解锁,之后A获得互斥锁,但它回去发现资源已经被使用了,它便有两个选择,一个失去访问不存在的资源,另一个就是继续等待,那么等待下去的条件就是使用while,要不然使用if的话pthread_cond_wait返回后,就会顺序执行下去。

等待线程:

pthread_cond_wait      前要加锁

pthread_cond_wait      内部会解锁,然后等待条件变量被其他线程激活

pthread_cond_wait      被激活后会再自动加锁

激活线程

加锁(和等待线程用同一个锁)

pthread_cond_signal   发送信号(阶跃信号前最后判断有无等待线程)

解锁

激活线程的上面三个操作再运行时间上都是再等待线程的pthread_cond_wait函数内部。

  1. /***
  2. pthread_if.c
  3. ***/
  4. #include<stdio.h>
  5. #include<sys/types.h>
  6. #include<stdlib.h>
  7. #include<unistd.h>
  8. #include<pthread.h>
  9.  
  10. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  11. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  12.  
  13. int count = ;
  14.  
  15. void *decrement(void *arg)
  16. {
  17. printf("in derment\n");
  18. pthread_mutex_lock(&mutex);
  19. if(count == )
  20. pthread_cond_wait(&cond,&mutex);
  21. count--;
  22. printf("----decrement:%d\n",count);
  23. printf("out decrement\n");
  24. pthread_mutex_unlock(&mutex);
  25. return NULL;
  26. }
  27.  
  28. void *increment(void *arg)
  29. {
  30. printf("in increment\n");
  31. pthread_mutex_lock(&mutex);
  32. count++;
  33. printf("-----increment:%d\n",count);
  34. if(count != )
  35. {
  36. pthread_cond_signal(&cond);
  37. }
  38. printf("out increment\n");
  39. pthread_mutex_unlock(&mutex);
  40. return NULL;
  41. }
  42.  
  43. int main()
  44. {
  45. pthread_t tid_in,tid_de;
  46. pthread_create(&tid_de,NULL,(void*)decrement,NULL);
  47. sleep();
  48. pthread_create(&tid_in,NULL,(void*)increment,NULL);
  49. sleep();
  50.  
  51. pthread_join(tid_de,NULL);
  52. pthread_join(tid_in,NULL);
  53. pthread_mutex_destroy(&mutex);
  54. pthread_cond_destroy(&cond);
  55. return ;
  56. }
  1. /***
  2. pthread_while.c
  3. ***/
  4. #include<stdio.h>
  5. #include<stdlib.h>
  6. #include<pthread.h>
  7. #include<unistd.h>
  8.  
  9. typedef struct node_s
  10. {
  11. int data;
  12. struct node_s *next;
  13. }node_t;
  14.  
  15. node_t *head = NULL;
  16.  
  17. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  18. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  19.  
  20. void cleanup_handler(void *arg)
  21. {
  22. printf("cleanup_handler is running.\n");
  23. free(arg);
  24. pthread_mutex_unlock(&mutex);
  25. }
  26.  
  27. void *thread_func(void *arg)
  28. {
  29. node_t *p = NULL;
  30. pthread_cleanup_push(cleanup_handler,p);
  31. while()
  32. {
  33. pthread_mutex_lock(&mutex);
  34. while(NULL == head)
  35. pthread_cond_wait(&cond,&mutex);
  36. p = head;
  37. head = head->next;
  38. printf("process %d node\n",p->data);
  39. free(p);
  40. pthread_mutex_unlock(&mutex);
  41. }
  42. pthread_cleanup_pop();
  43. return NULL;
  44. }
  45.  
  46. int main()
  47. {
  48. pthread_t tid;
  49. node_t *temp = NULL;
  50. int i;
  51. pthread_create(&tid,NULL,(void*)thread_func,NULL);
  52.  
  53. for(i = ; i < ; i++)
  54. {
  55. temp = (node_t*)malloc(sizeof(node_t));
  56. temp->data = i;
  57. pthread_mutex_lock(&mutex);
  58. temp->next = head;
  59. head = temp;
  60. pthread_cond_signal(&cond);
  61. pthread_mutex_unlock(&mutex);
  62. sleep();
  63. }
  64. pthread_cancel(tid);
  65. pthread_join(tid,NULL);
  66. return ;
  67.  
  68. }

linux线程操作的更多相关文章

  1. linux 线程操作问题undefined reference to 'pthread_create'的解决办法(cmake)

    问题原因: pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a. 所以在使用pthread_create()创建线程时,需要链接该库. 1. 终端:问题解 ...

  2. 8)Linux程序设计入门--线程操作

    )Linux程序设计入门--线程操作 前言:Linux下线程的创建 介绍在Linux下线程的创建和基本的使用. Linux下的线程是一个非常复杂的问题,由 于我对线程的学习不时很好,我在这里只是简单的 ...

  3. linux线程

    线程:轻量级进程,在资源.数据方面不需要进行复制 不间断地跟踪指令执行的路径被称为执行路线 进程的结构:task_struck:地址空间 线程:轻量级的进程 在同一个进程中创建的线程,在共享进程的地址 ...

  4. [转载]Linux 线程实现机制分析

    本文转自http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 支持原创.尊重原创,分享知识! 自从多线程编程的概念出现在 Linux ...

  5. linux线程的实现

    首先从OS设计原理上阐明三种线程:内核线程.轻量级进程.用户线程 内核线程 内核线程就是内核的分身,一个分身可以处理一件特定事情.这在处理异步事件如异步IO时特别有用.内核线程的使用是廉价的,唯一使用 ...

  6. linux线程的实现【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3620204.html 首先从OS设计原理上阐明三种线程:内核线程.轻量级进程.用户线程 内核线程 内核线程就是内核的分身,一个 ...

  7. Linux线程-创建

    Linux的线程实现是在内核以外来实现的,内核本身并不提供线程创建.但是内核为提供线程[也就是轻量级进程]提供了两个系统调用__clone()和fork (),这两个系统调用都为准备一些参数,最终都用 ...

  8. Linux线程学习(一)

    一.Linux进程与线程概述 进程与线程 为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同一个变量.所以,程序中的所有线程都可 ...

  9. Linux线程学习(二)

    线程基础 进程 系统中程序执行和资源分配的基本单位 每个进程有自己的数据段.代码段和堆栈段 在进行切换时需要有比较复杂的上下文切换   线程 减少处理机的空转时间,支持多处理器以及减少上下文切换开销, ...

随机推荐

  1. ④ Python3.0字符串

    字符串无论是python或者其他语言,是最常用的数据类型之一: 这儿注意在python中可以通过使用引号( ' 或 " )来创建字符串.使用三引号('''或""" ...

  2. jdk安装以及Java环境配置

    jdk其实自己大一的时候就已经装过,java环境也配置过,但是随着后面学习的东西越来越多,要安装的软件也越来越多,一开始没有安装路径的概念,好多东西都放的很乱.接着这次自己复习java的机会,于是重新 ...

  3. iOS应用状态保存和恢复

    当应用被后台Kill掉的时候希望从后台返回的时候显示进入后台之前的内容 在Appdelegate中设置 - (BOOL)application:(UIApplication *)application ...

  4. 限制mongoDB内存的方法

    docker运行MongoDB,针对于docker容器来进行内存资源的限制 修改MongoDB的运行配置文件,并且重启mongodb storage: dbPath: /var/lib/mongodb ...

  5. Vue.js源码中大量采用的ES6新特性介绍:模块、let、const

    1 关于ES6      ECMAScript6(以下简称ES6)是JavaScript语言的最新一代标准,发布于2015年6月,因为ECMA委员会决定从ES6起每年更新一次标准,因此ES6被改名为E ...

  6. 智能驾驶数据后处理分析利器—INTEWORK-VDA

            随着智能驾驶技术在新车上逐步普及,车辆研发阶段需要做大量的实车测试工作,当前的测试方式主要是路采实车数据后,按标准和法规进行测试场景提取和测试数据分析.调查显示绝大部分智能驾驶研发厂商 ...

  7. sshd安全加固

    常见的防护措施: ——用户限制,黑白名单 ——更改验证方式(密码——>密钥对) ——防火墙..... 修改 sshd 配置文件 /etc/ssh/sshd_config -port 3389 # ...

  8. RNN、LSTM介绍以及梯度消失问题讲解

    写在最前面,感谢这两篇文章,基本上的框架是从这两篇文章中得到的: https://zhuanlan.zhihu.com/p/28687529 https://zhuanlan.zhihu.com/p/ ...

  9. springboot学习笔记(二)—— springboot的启动模式设置

    把springboot的启动类图标(spring)去掉,在启动类中添加以下代码 package com.xdr.spring; import org.springframework.boot.Bann ...

  10. django-ContentType的简单使用

    ContentType 一般我们有多张表同时外键关联同一张表的时候,可以考虑使用ContentType models.py from django.db import models from djan ...