线程控制(linux C)
来源:互联网 发布:视频去除马赛克软件 编辑:程序博客网 时间:2024/06/16 19:32
线程是计算机中独立运行的最小单位,运行占用资源很小,宏观上线程同时执行。微观上通过系统分配时间片去的CPU控制权交替执行线程中的代码。当然多核情况下是可以并行的。
目录
- 线程优点
- 线程私有数据
- 线程的同步方法
线程的优点
1.节省资源,节省时间。多进程时,每个进程都拥有独立的空间,而同进程下的多线程共享进程的地址空间。同时也节省了为其分配空间所花费的时间。
2.因为地址空间共享,所以线程间的切换速度远快于进程。
3.线程共享空间,通信更加方便。
私有数据
1.线程ID。唯一标识,基本调用阿关闭阿传信号阿都是用它。
2.寄存器。包括程序计数器和堆栈指针。
3.堆栈。
4.信号掩码。
优先级。
线程私有的存储空间
线程私有数据可以被线程内各个函数访问,但对其他线程是屏蔽的。
线程私有数据采用一键多值的技术,访问数据时通过键值来访问的,就是好像在对一个变量进行访问,其实是在访问不同的数据,所以在使用私有数据前,要先为每个线程创建一个相关联的键。
测试代码:
#include <stdio.h>#include <string.h>#include <pthread.h>pthread_key_t key;void *thread2(void *arg){ int tsd = 5; printf("thread %d is running\n", pthread_self()); pthread_setspecific(key, (void *)tsd); printf("thread %d return %d\n", pthread_self(), pthread_getspecific(key));}void *thread1( void *arg ){ int tsd = 0; pthread_t thid2; printf("thread %d is running\n", pthread_self()); pthread_setspecific( key, (void *)tsd ); pthread_create(&thid2, NULL, thread2, NULL); sleep(2); printf("thread %d return %d\n", pthread_self(), pthread_getspecific(key));}int main( int argc, char *argv ){ pthread_t thid1; printf("main thread begigs running\n"); pthread_key_create( &key, NULL ); pthread_create( &thid1, NULL, thread1, NULL ); sleep(3); pthread_key_delete( key ); printf("main thread exit\n"); return 0;}
主要函数:
//从TSD池中分配一项,将值赋给key,destr_function为清理函数 int pthread_key_create( pthread_key_t *key, void (*destr_function)(void *)); //将pointer的值与key相关联 int pthread_setspecific(pthread_key_t key, const void *pointer);//得到与key相关联的数据void *pthread_getsspecific( pthread_key_t key);//用来删除键,释放键所占用的内存 int pthread_key_delete(pthread_key_t key);
运行结果:
代码中,main函数创建线程1,线程1创建线程2,他们共用全局变量key为键值,但是私有数据tsd不同。主要函数是线程内部函数pthread_setspecific(key, tsb)将key键和tsb值相关联,实现一键多值。
线程创建
有时需要控制线程仅执行一次,下面的代码尝试实现这个要求。
#include<stdio.h>#include <pthread.h>pthread_once_t once = PTHREAD_ONCE_INIT;void run(void){ printf("Function run is running in thread %u\n", pthread_self()); //pthread_self()函数得到当前线程的ID}void *thread1(void *arg){ printf("Current thread's id is %u\n", pthread_self()); pthread_once(&once, run); //此函数用来保证函数执行一次 printf("thread1 ends\n");}void *thread2(void *arg){ printf("Current thread's id is %u\n", pthread_self()); pthread_once(&once, run); printf("thread2 end\n");}int main(){ pthread_t thid1, thid2; pthread_create(&thid1, NULL, thread1, NULL); pthread_create(&thid2, NULL, thread2, NULL); sleep(3); printf("main thread exit!\n"); exit(0);}
运行结果:
可以看出函数run中的Function run…了一次。
线程同步
线程最大的特点就是同步性。但是同步时资源分配问题就成了难题。linux下提供互斥锁,条件变量,和异步信号来处理这个问题。
互斥锁
锁的使用比较简单,利用pthread_mutex_init()初始化一个互斥锁就可以使用了,使用方法如下:
pthread mutex_t number_mutex; //互斥锁pthread_mutex_lock(&number_mutex); //加锁globalnumber ++; //某全局变量pthread_mutex_unlock(&number_mutex); //解锁
当使用pthread_mutex_lock()加锁时,使用全部变量过程中,别的线程就无权访问它,除非解锁。
来看几个相关函数:
pthread_mutex_init(); 初始化一个互斥锁
pthread_mutex_destroy(); 注销一个互斥锁
pthread_mutex_lock(); 加锁,如果不成功,阻塞等待
pthread_mutex_unlock(); 解锁
pthread_mutex_trylock(); 尝试加锁。如果不成功立即返回,错误码为EBUSY
条件变量
条件变量宏观上类似if语句,符合条件就能执行某段程序,否则只能等待条件成立。
使用条件变量主要包括两个动作,一个等待使用资源的线程等待“条件变量被设置为真”,另一个线程在使用完资源后,“设置条件为真”。
条件变量一般配合互斥锁使用。
主要函数:
pthread_cond_init(); //初始化条件变量pthread_cond_wait(); //基于条件变量阻塞,无条件等待pthread_cond_timewait(); // 阻塞直到时间发生,计时等待pthread_cond_signal(); // 解决特定线程的等待pthread_cond_broadcast(); // 解除所有线程的阻塞pthread_cond_destory(); //清除条件变量
异步信号
信号与任何线程都是异步的,也就是说信号到达线程的时间是不定的,
处理异步信号的函数:
//向线程threadid发送信号SIGNOint pthread_kill(pthread_t threadid, int signo);//设置线程的信号屏蔽码int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);//阻塞线程,等待set中某一信号到达,将其存入*sigint sigwait(const sigset_t *set, int *sig);
- 线程控制(linux C)
- linux c编程--线程控制及通信
- linux c学习之线程控制
- Linux&C 线程控制 课后习题
- Linux下的C编程入门(四)――“线程”控制与“线程”通信编程
- Linux下的C编程实战(四)--“线程”控制与“线程”通信编程
- LINUX下的C编程入门(四)――“线程”控制与“线程”通信编程
- Linux下的C编程实战(四)――“线程”控制与“线程”通信编程
- Linux下的C编程实战(四)――“线程”控制与“线程”通信编程
- Linux C编程学习笔记(7):线程控制
- linux线程控制&线程分离
- linux 的线程控制
- Linux信号量线程控制
- Linux信号量线程控制
- Linux/UNIX线程控制
- Linux/UNIX线程控制
- Linux - 线程属性控制
- Linux学习--线程控制
- CHR(n1)
- boosting之从GB到GBDT再到Xgboost
- 三角函数
- 利用反射机制实现工厂模式
- sqrt(x)
- 线程控制(linux C)
- 有关过多if-else代码的优雅解决方式(搭配注解替代枚举的方法)
- ubuntu14.04中关于flash插件在firefox无法使用的解决方法
- C语言的项目开发模型(1)-字符串两头堵
- Java反射结合属性文件实现工厂模式
- Perfect Squares
- 第六天:二维数组和 面向对象的思想
- 数组(数组与泛型待补充,深浅拷贝待补充)
- 实现三级缓存加载图片