Linux下的线程
一、线程的优点
与传统进程相比,用线程来实现相同的功能有如下优点:
(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下的线程的更多相关文章
- Linux下查看线程数的几种方法汇总
Linux下查看线程数的几种方法汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux下查看某个进程的线程数量 pstree命令以树状图显示进程间的关系(display ...
- Linux下Java线程具体监控和其dump的分析使用----分析Java性能瓶颈[张振华-Jack]
作者:张振华(Jack) 这里对linux下.sun(oracle) JDK的线程资源占用问题的查找步骤做一个小结: linux环境下,当发现java进程占用CPU资源非常高,且又要想更进一步查出哪一 ...
- Linux下进程线程,Nignx与php-fpm的进程线程方式
1.进程与线程区别 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流, ...
- Linux下简单线程池的实现
大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个服务请求到达,就创建一个新的服务 ...
- 一个Linux下C线程池的实现
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...
- linux下的线程池
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...
- linux下使用线程锁互斥访问资源
linux使用线程锁访问互斥资源: 1.线程锁的创建 pthread_mutex_t g_Mutex; 2.完整代码如下 #include <stdio.h> #include <s ...
- Linux下获取线程TID的方法——gettid()
(转载)http://blog.csdn.net/delphiwcdj/article/details/8476547 如何获取进程的PID(process ID)? 可以使用: #include & ...
- Linux下简易线程池
线程池简介 线程池是可以用来在后台执行多个任务的线程集合. 这使主线程可以自由地异步执行其他任务.线程池通常用于服务器应用程序. 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会 ...
随机推荐
- 性能测试-ApacheBench
基本简介 ApacheBench 是一个指令列程式,专门用来执行网站服务器的运行效能,特别是针对Apache 网站服务器.这原本是用来检测 Apache 网站服务器能够提供的效能,特别是可以看出Apa ...
- Use weakref module in a cache or mapping
The weakref module allows the Python programmer to create weak references to objects. In the followi ...
- poj 3006 Dirichlet's Theorem on Arithmetic Progressions
题目大意:a和d是两个互质的数,则序列a,a+d,a+2d,a+3d,a+4d ...... a+nd 中有无穷多个素数,给出a和d,找出序列中的第n个素数 #include <cstdio&g ...
- 新工程软连接到原来的工程的out目录后,可以直接编译模块
P508B_App_old_developer/alps$ ln -s ../../P508B_App/alps/out 连接后,第一次编译后要加分支 ./mk hedy89_we_jb2 mm p ...
- Hadoop Java开发实用快捷键收藏
不断总结更新.... Alt + / 补全 Ctrl + T 打出结构 Ctrl + 2 ,再选择 Quick Assist - Assign to local variable Ctrl ...
- ubuntu下设置开机自动挂载硬盘
我们在linux中常常用mount命令把硬盘分区或者光盘挂载到文件系统中./etc/fstab就是在开机引导的时候自动挂载到linux的文件系统. 如果给计算机配了一块新磁盘,已经分区,格式化,挂载, ...
- POJ 2318 TOYS (计算几何,叉积判断)
TOYS Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8661 Accepted: 4114 Description ...
- 使用python通过SSH登陆linux并操作
用的昨天刚接触到的库,在windows下通过paramiko来登录linux系统并执行了几个命令,基本算是初试成功,后面会接着学习的. 代码: >>> import paramiko ...
- 使用VS2013调试FluorineFx程序
VS2013,建立 FluorineFx Web 项目方法: 先新建.项目.Web.选择.NET 3.5 ASP.NET 窗体程序来新建一个项目.复制 log.Templates.WEB-INF 文件 ...
- android 绘图之Canvas,Paint类
Canvas,Paint 1.在android 绘图但中经常要用到Canvas和Paint类,Canvas好比是一张画布,上面已经有你想绘制图画的轮廓了,而Paint就好比是画笔,就要给Canvas进 ...