Linux线程(pthread)学习笔记(一)
来源:互联网 发布:python DAG教程 编辑:程序博客网 时间:2024/05/28 05:18
声明:本文内容参考自:
http://fanqiang.chinaunix.net/a4/b8/20010811/0905001105.html Linux下的多线程编程
http://blog.csdn.net/lhf_tiger/article/details/8291984 pthrad_attr_setdetachstate
http://blog.csdn.net/ithomer/article/details/6063067 Linux多线程Pthread学习小结
等大神的博客~具体的不一一列出了
好了,回归正文
Linux系统下的多线程遵循POSIX线程接口,称为pthread
使用多线程的优点:
众所周知创建一个线程的开销远比创建一个进程的开销要小的多.
启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,
这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,
共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便
提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况
使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
pthread_exit():终止当前线程
pthread_join():阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init():初始化线程的属性
pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_kill():向线程发送一个信号
pthread_mutex_init() 初始化互斥锁
pthread_mutex_lock():占有互斥锁(阻塞操作)
pthread_mutex_trylock():试图占有互斥锁(不阻塞操作)。当互斥锁空闲时将占有该锁;否则立即返回
pthread_mutex_unlock(): 释放互斥锁
pthread_mutex_unlock(): 释放互斥锁
pthread_cond_init():初始化条件变量
pthread_cond_destroy():销毁条件变量
线程的合并与分离:
我们首先要明确的一个问题就是什么是线程的合并。从前面的叙述中读者们已经了解到了,pthread_create()接口负责创建了一个线程。那么线程也属于系统的资源,这跟内存没什么两样,而且线程本身也要占据一定的内存空间。众所周知的一个问题就是C或C++编程中如果要通过malloc()或new分配了一块内存,就必须使用free()或delete来回收这块内存,否则就会产生著名的内存泄漏问题。既然线程和内存没什么两样,那么有创建就必须得有回收,否则就会产生另外一个著名的资源泄漏问题,这同样也是一个严重的问题。那么线程的合并就是回收线程资源了。
int pthread_attr_init(pthread_attr_t *attr);int pthread_attr_destory(pthread_attr_t *attr);Linux下的线程有:绑定属性、分离属性、调度属性、堆栈大小属性和满占警戒区大小属性.
既然叫锁,就有加锁和解锁的概念。当线程获得了加锁的资格,那么它将独享这个锁,其它线程一旦试图去碰触这个锁就立即被系统“拍晕”。
从互斥锁的这种行为看,线程加锁和解锁之间的代码相当于一个独木桥,同意时刻只有一个线程能执行。从全局上看,在这个地方,
互斥锁在Linux中的名字是mutex。这个似乎优点眼熟。对,在前面介绍NPTL的时候提起过,但是那个叫futex,是系统底层机制。
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);int pthread_mutex_destory(pthread_mutex_t *mutex );int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_t counter_lock;......//初始化pthread_mutex_init(&counter_lock, NULL);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);int pthread_cond_destory(pthread_cond_t *cond);int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, const timespec *abstime);int pthread_cond_signal(pthread_cond_t *cond);int pthread_cond_broadcast(pthread_cond_t *cond);对于等待“事件”的接口从其名称中可以看出,一种是无限期等待,一种是限时等待。后者与互斥锁的pthread_mutex_trylock()有些类似,即当等待的“事件”经过一段时间之后依然没有发生,那就去干点别的有意义的事情去。而对于控制“事件”发生的接口则有“单播”和“广播”之说。所谓单播就是只有一个线程会得到“事件”已经发生了的“通知”,而广播就是所有线程都会得到“通知”。对于广播情况,所有被“通知”到的线程也要经过由互斥锁控制的独木桥。
#include <stdio.h>#include <pthread.h>#include <unistd.h>pthread_mutex_t counter_lock; //互斥锁pthread_cond_t counter_nonzero; //条件变量int counter = 0;int estatus = -1;void *decrement_counter(void *argv);void *increment_counter(void *argv);//******* 主函数 *******//int main(int argc, char **argv){ printf("counter: %d/n", counter); pthread_t thd1, thd2; int ret; //初始化 pthread_mutex_init(&counter_lock, NULL); pthread_cond_init(&counter_nonzero, NULL); ret = pthread_create(&thd1, NULL, decrement_counter, NULL); //创建线程1 if(ret){ perror("del:/n"); return 1; } ret = pthread_create(&thd2, NULL, increment_counter, NULL); //创建线程2 if(ret){ perror("inc: /n"); return 1; } int counter = 0; while(counter != 10){ printf("counter(main): %d/n", counter); //主线程 sleep(1); counter++; } pthread_exit(0); return 0;}void *decrement_counter(void *argv){ printf("counter(decrement): %d/n", counter); pthread_mutex_lock(&counter_lock); while(counter == 0) pthread_cond_wait(&counter_nonzero, &counter_lock); //进入阻塞(wait),等待激活(signal) printf("counter--(before): %d/n", counter); counter--; //等待signal激活后再执行 printf("counter--(after): %d/n", counter); pthread_mutex_unlock(&counter_lock); return &estatus;}void *increment_counter(void *argv){ printf("counter(increment): %d/n", counter); pthread_mutex_lock(&counter_lock); if(counter == 0) pthread_cond_signal(&counter_nonzero); //激活(signal)阻塞(wait)的线程(先执行完signal线程,然后再执行wait线程) printf("counter++(before): %d/n", counter); counter++; printf("counter++(after): %d/n", counter); pthread_mutex_unlock(&counter_lock); return &estatus;}运行结果:
counter(main): 0
counter(decrement): 0
counter(increment): 0
counter++(before): 0
counter++(after): 1
counter--(before): 1
counter--(after): 0
counter(main): 1
counter(main): 2
counter(main): 3
counter(main): 4
counter(main): 5
counter(main): 6
counter(main): 7
counter(main): 8
counter(main): 9
- Linux线程(pthread)学习笔记(一)
- pthread线程学习笔记一
- Linux线程(pthread)学习笔记
- Linux线程pthread笔记
- linux pthread线程学习
- [Linux]pthread学习笔记
- pthread学习笔记(一)
- Linux 多线程编程(Pthread 库)学习笔记 一
- UNIX/LINUX编程学习之线程pthread
- 线程-Pthread 笔记
- Linux 多线程编程(Pthread 库)学习笔记
- Linux 线程 pthread
- linux pthread 线程库
- linux pthread线程详解
- linux 线程 pthread
- linux pthread 线程详解
- Linux pthread 线程 浅解
- linux线程pthread互斥锁
- android布局标签<include />使用
- (转载)Android数据库高手秘籍(六)——LitePal的修改和删除操作
- zoj1610 Count the Colors(线段树)
- Linux系统调用--getrlimit()与setrlimit()函数详解
- Android Parcelable和Serializable的区别
- Linux线程(pthread)学习笔记(一)
- Restore IP Addresses (Java)
- LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- SOA Header的处理
- Android代码混淆
- IOS 图片拉伸技巧
- VC下进行串口开发的简单说明
- IRP
- FPGA LVDS应用