一、线程的优点

与传统进程相比,用线程来实现相同的功能有如下优点:

(1)系统资源消耗低。

(2)速度快。

(3)线程间的数据共享比进程间容易的多。

二、多线程编程简单实例

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h> void
thread1_routine(void)
{
printf("new thread:thread_id is %u, process_id is %u\n",
pthread_self(), getpid());
}
void
thread2_routine(void)
{
printf("new thread:thread_id is %u, process_id is %u\n",
pthread_self(), getpid());
} int
main(void)
{
pthread_t pt;
printf("old thread:thread_id is %u, process_id is %u\n",
pthread_self(), getpid());
pthread_create(&pt, NULL, (void *)thread1_routine, NULL);
pthread_create(&pt, NULL, (void *)thread2_routine, NULL);
usleep(5);
return(0);
}

运行结果如下(可以看出在同一个进程中有三个不同的线程同时在运行):

三、线程属性

线程属性包括绑定属性、分离属性、堆栈地址、堆栈大小和优先级。其中分离属性、堆栈地址以及堆栈大小的介绍可参考http://www.cnblogs.com/nufangrensheng/p/3522583.html。系统默认的是非邦定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。

1、绑定属性

线程可以分为用户级线程和内核级线程两种(可参考http://blog.csdn.net/songjinshi/article/details/9042265以及http://www.xuebuyuan.com/1380720.html),而绑定属性正是设置用户级线程和内核级线程之间的关系。

绑定属性分为两种:绑定和非绑定。在绑定属性下,一个用户级线程固定分配给一个内核线程,因为CPU时间片的调度是面向内核线程(轻量级进程)的,因此具有 绑定属性的线程可以保证在需要的时候总有一个内核线程与之对应。在非绑定属性下,用户线程和内核线程的关系不是始终固定的,而是由系统根据实际情况分配的。

2、优先级

四、线程互斥

生产者消费者实例(多线程+互斥量):

#include <stdio.h>
#include <pthread.h>
#include <sched.h> void *producter_f(void *arg);
void *consumer_f(void *arg); int buffer_has_item = 0;
pthread_mutex_t mutex;
int running = 1; int
main(void)
{
pthread_t consumer_t;
pthread_t producter_t; pthread_mutex_init(&mutex, NULL); pthread_create(&producter_t, NULL, (void *)producter_f, NULL); pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL); sleep(1); /* 等待线程创建完毕 */
running = 0;
pthread_join(consumer_t, NULL);
pthread_join(producter_t, NULL);
pthread_mutex_destroy(&mutex); return(0);
} void *
producter_f(void *arg)
{
while(running)
{
if(buffer_has_item < 10) /* 最多允许生产10个 */
{
pthread_mutex_lock(&mutex);
buffer_has_item++;
printf("product, total: %d\n", buffer_has_item);
pthread_mutex_unlock(&mutex);
}
}
} void *
consumer_f(void *arg)
{
while(running)
{
if(buffer_has_item > 0) /* 缓冲区为空时不允许再消费 */
{
pthread_mutex_lock(&mutex);
buffer_has_item--;
printf("consume, total: %d\n", buffer_has_item);
pthread_mutex_unlock(&mutex);
}
}
}

编译运行结果如下:

 

五、线程中使用信号量

(此处使用的信号量是POSIX无名信号量:http://www.cnblogs.com/nufangrensheng/p/3564306.html

线程的信号量与进程的信号量类似,使用线程的信号量可以高效地完成基于线程的资源计数。信号量实际上是一个非负的整数计数器,用来实现对公共资源的控制。在公共资源增加的时候,信号量的值增加;公共资源消耗的时候,信号量的值减少;只有当信号量的值大于0时,才能允许访问信号量所代表的公共资源。

生产者消费者实例(多线程+信号量):

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h> void *producter_f(void *arg);
void *consumer_f(void *arg); sem_t sem;
int running = 1; int
main(void)
{
pthread_t consumer_t;
pthread_t producter_t; sem_init(&sem, 0, 16); pthread_create(&producter_t, NULL, (void *)producter_f, NULL); pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL); sleep(1);
running = 0;
pthread_join(consumer_t, NULL);
pthread_join(producter_t, NULL);
sem_destroy(&sem); return(0);
} void *
producter_f(void *arg)
{
int semval = 0;
while(running)
{
usleep(1);
sem_post(&sem);
sem_getvalue(&sem, &semval);
printf("product, total: %d\n", semval);
}
} void *
consumer_f(void *arg)
{
int semval = 0;
while(running)
{
usleep(1);
sem_wait(&sem);
sem_getvalue(&sem, &semval);
printf("consume, total: %d\n", semval);
}
}

编译运行如下:

 

更多关于线程的介绍可参考http://www.cnblogs.com/nufangrensheng/p/3518114.html及其后续博文。

Linux下的线程的更多相关文章

  1. Linux下查看线程数的几种方法汇总

    Linux下查看线程数的几种方法汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux下查看某个进程的线程数量 pstree命令以树状图显示进程间的关系(display ...

  2. Linux下Java线程具体监控和其dump的分析使用----分析Java性能瓶颈[张振华-Jack]

    作者:张振华(Jack) 这里对linux下.sun(oracle) JDK的线程资源占用问题的查找步骤做一个小结: linux环境下,当发现java进程占用CPU资源非常高,且又要想更进一步查出哪一 ...

  3. Linux下进程线程,Nignx与php-fpm的进程线程方式

    1.进程与线程区别 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流, ...

  4. Linux下简单线程池的实现

    大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个服务请求到达,就创建一个新的服务 ...

  5. 一个Linux下C线程池的实现

    什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...

  6. linux下的线程池

    什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...

  7. linux下使用线程锁互斥访问资源

    linux使用线程锁访问互斥资源: 1.线程锁的创建 pthread_mutex_t g_Mutex; 2.完整代码如下 #include <stdio.h> #include <s ...

  8. Linux下获取线程TID的方法——gettid()

    (转载)http://blog.csdn.net/delphiwcdj/article/details/8476547 如何获取进程的PID(process ID)? 可以使用: #include & ...

  9. Linux下简易线程池

    线程池简介 线程池是可以用来在后台执行多个任务的线程集合. 这使主线程可以自由地异步执行其他任务.线程池通常用于服务器应用程序. 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会 ...

随机推荐

  1. Yii 1 数据库操作 笔记

    $result = array( 'id'=>null, 'val'=>0 ); $row1 = Yii::app()->db->createCommand()->ins ...

  2. geeksforgeeks@ Minimum sum partition (Dynamic Programming)

    http://www.practice.geeksforgeeks.org/problem-page.php?pid=166 Minimum sum partition Given an array, ...

  3. CSRF的攻击与防御(转)

    add by zhj:CSRF之所有发生,是因为http请求中会自动带上cookies,我的解决办法是:前端不要将数据放在cookie中,而是放在其它本地存储 (HTML5中称之为Web Storag ...

  4. show index 之Cardinality (mysql)

    show index  之Cardinality 官方文档的解释: Cardinality An estimate of the number of unique values in the inde ...

  5. gcc -D

    [gcc -D] -D name Predefine name as a macro, with definition 1. 通常debug和release版的区别就在于是否有DEBUG宏,DEBUG ...

  6. Client Dependency学习

    Client Dependency Framework ---CDF CDF is a framework for managing CSS & JavaScript dependencies ...

  7. HDU1002大数加法

    大数加法 c++版: #include <map> #include <set> #include <stack> #include <queue> # ...

  8. UVaLive 6802 Turtle Graphics (水题,模拟)

    题意:给定一个坐标,和一行命令,按照命令走,问你有多少点会被访问超过一次. 析:很简单么,按命令模拟就好,注意有的点可能走了多次,只能记作一次. 代码如下: #pragma comment(linke ...

  9. https,https的本地测试环境搭建,asp.net结合https的代码实现,http网站转换成https网站之后遇到的问题

    一:什么是https SSL(Security   Socket   Layer)全称是加密套接字协议层,它位于HTTP协议层和TCP协议层之间,用于建立用户与服务器之间的加密通信,确保所传递信息的安 ...

  10. UI进阶 科大讯飞(1) 语音听写(语音转换成文字)

    一.科大讯飞开放平台: http://www.xfyun.cn/ 注册.登录之后创建新应用. 因为本项目只实现了语音听写,所以在SDK下载中心勾选语音听写单项SDK就可以了 开发平台选择iOS,应用选 ...