一、线程的优点

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

(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. Windows Server 2003单网卡搭建VPN

    Windows Server 2003单网卡搭建VPN   1.打开[控制面板] --> [管理工具] --> [路由和远程访问] 2.鼠标右击你要管理的电脑 在弹出式菜单中选中[配置并启 ...

  2. geeksforgeeks@ Sorting Elements of an Array by Frequency (Sort)

    http://www.practice.geeksforgeeks.org/problem-page.php?pid=493 Sorting Elements of an Array by Frequ ...

  3. matlab 画锥体

    >> plot3(x,y,z); >> [x,y,z]=cylinder([ ],)

  4. 在VS2013中使用水晶报表

    又遇到了在B/S系统中打印,打印格式要求比较高,打印出的效果要求高大上.用VS2013中微软自带的报表,实在难以实现应用的效果,主要问题表现在: 1.不能插入用Word做好的打印模板,自己按照模板来做 ...

  5. MSSQL 2005数据库可疑状态

    今天早上打开进销存,提示链接失败,经过检查参数,网络.端口等各种情况,均没有发现问题,最后检查数据库本事的问题. 通过studio进去发现我的进销存数据变成了(可疑)状态,随机百度修复方法,修复方法还 ...

  6. 关于网上流传的四个原版Windows XP_SP2全面了解

    如何查看你的XP SP2是否原版?打开Windows/System32/找到EULA这个文本文档(即eula.txt):打开在最后一行:有一个EULAID:XPSP2_RM.0_PRO_RTL_CN ...

  7. UVaLive 6805 Pantun Grader (恶心的模拟)

    题意:给定 n 首诗,然后让你给他打分,有四种规则,第一种是按音节打,如果音节在8-12之间,就加10,第二种就是按押韵打,如果13,24一个押韵就加20分. 第三种按音节数打,13,24有一个一样的 ...

  8. Oracle数据库编程:在JDBC中应用Oracle

    9.在JDBC中应用Oracle: JDBC访问数据库基本步骤:          1.加载驱动          2.获取链接对象          3.创建SQL语句          4.提交S ...

  9. UITextfiled子视图被剪切

    一般情况下,如果在view1上面添加了view2,但是view2超出了view1,也会在屏幕上面显示超出的部分 例如: UIButton *button =[[UIButton alloc]initW ...

  10. Dubbo远程调用服务框架原理与示例

    Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 主要核心部件: Remoting: 网络通信框架 ...