linux下线程控制
2015-10-25 12:51
531 查看
线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。在多进程情况下,每个进程都有自己独立的地址空间,而在多线程情况下,同意进程内的线程共享进程的地址空间。因此创建新进程就要耗费时间为其分配系统资源,而创建新线程花费的时间要少得多。
1.创建线程
1.程序结束所有子线程就结束
解决办法: 等待子线程结束
a.sleep/pause
b.pthread_exit(void*retval);
c.int pthread_join(
pthread_t tid, //等待子线程tid结束
void **retval); //子线程结束的返回值
如果不加等待子线程结束的语句,main函数执行完会直接退出,不会执行子线程
2.创建子线程后,主线程继续完成系统分配的时间片
3.子线程结束就是线程函数返回
4.子线程与主线程有同等优先级别
2.线程基本控制
线程结束可分为内部结束和外部结束:
内部自动结束:(建议,可以看例二)
return 返回值; 只能在线程函数中使用
int pthread_exit(void*); 在任何线程代码中都可以使用,退出当前线程
外部结束一个线程(处理可以参看下边介绍,防止产生问题):
pthread_cancel(pthread_t thread); 会产生一些不可预知的问题
例二:内部结束线程
对于一个全局变量资源等信息,线程是共享进程的这些资源,存在多个线程对这些数据资源进行操作时,可能会产生一些问题,导致数据成为脏数据。
为了解决数据脏,可以使用加锁机制;
3.1.互斥锁/互斥量 mutex(强烈要求成对使用,加锁就需要解锁)
(1).定义互斥量 pthread_mutex_t m;
(2).初始化互斥量 1 pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
attr为锁的属性,置NULL/0为默认属性
(3).互斥量操作
置0 pthread_mutex_lock
会判定互斥量若为0:阻塞;为1:先置0,再返回
置1 pthread_mutex_unlock 直接置1返回
(4).释放互斥量pthread_mutex_destroy
例三:使用互斥锁
![](http://s3.51cto.com/wyfs02/M00/74/DC/wKiom1YsV5_ySNv5AAByyuQn-os438.jpg)
为了防止这种数据脏的问题,就需要使用互斥锁机制。
3.2死锁问题
在lock与unlock之间,调用pthread_exit或者在线程外部调用pthread_cancel会使其他线程被永久死锁。
pthread_exit退出线程,为了防止造成死锁,可以在pthread_exit语句前使用解锁语句unlock;
pthread_cancel退出线程,防止死锁可以使一对宏,这对宏类似于进程atexit函数:
push进去的函数可能在以下三个时机执行:
1,显示的调用pthread_exit();
2,在cancel点线程被cancel。
3,pthread_cleanup_pop()的参数不为0时。
例四:创建两个线程分别输出奇数和偶数
1.创建线程
int pthread_create( pthread_t *thread, //线程ID const pthread_attr_t *attr, //线程属性,为NULL/0,使用默认属性 void *(*start_routine) (void *), //线程代码函数 void *arg); //传递线程代码的数据
例1.创建线程 #include <stdio.h> #include <stdlib.h> #include <pthread.h> //这是一个外部库,在编译时需要指定链接库-lpthread void * thread(void *data) { printf("this is thread111,threadid = %ld\n",pthread_self()); } int main() { pthread_t thid; pthread_create(&thid,NULL,thread,NULL); //sleep(2); pthread_join(thid,(void**)0); return 0; }结论:
1.程序结束所有子线程就结束
解决办法: 等待子线程结束
a.sleep/pause
b.pthread_exit(void*retval);
c.int pthread_join(
pthread_t tid, //等待子线程tid结束
void **retval); //子线程结束的返回值
如果不加等待子线程结束的语句,main函数执行完会直接退出,不会执行子线程
2.创建子线程后,主线程继续完成系统分配的时间片
3.子线程结束就是线程函数返回
4.子线程与主线程有同等优先级别
2.线程基本控制
线程结束可分为内部结束和外部结束:
内部自动结束:(建议,可以看例二)
return 返回值; 只能在线程函数中使用
int pthread_exit(void*); 在任何线程代码中都可以使用,退出当前线程
外部结束一个线程(处理可以参看下边介绍,防止产生问题):
pthread_cancel(pthread_t thread); 会产生一些不可预知的问题
例二:内部结束线程
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <sched.h> void * thread(void *data) { while(1){ printf("this is thread data:%s\n",data); //return "thread exit"; pthread_exit("exit"); } } int main() { pthread_t thid; char *retavl; char *data="main"; pthread_create(&thid,NULL,thread,data); pthread_join(thid,(void**)&retavl); printf("%s\n",retavl); return 0; }
#gcc pthread_exit.c -o pthread_exit -lpthread #./pthread_exit this is thread data:main exit3.多线程问题及介绍
对于一个全局变量资源等信息,线程是共享进程的这些资源,存在多个线程对这些数据资源进行操作时,可能会产生一些问题,导致数据成为脏数据。
为了解决数据脏,可以使用加锁机制;
3.1.互斥锁/互斥量 mutex(强烈要求成对使用,加锁就需要解锁)
(1).定义互斥量 pthread_mutex_t m;
(2).初始化互斥量 1 pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
attr为锁的属性,置NULL/0为默认属性
(3).互斥量操作
置0 pthread_mutex_lock
会判定互斥量若为0:阻塞;为1:先置0,再返回
置1 pthread_mutex_unlock 直接置1返回
(4).释放互斥量pthread_mutex_destroy
例三:使用互斥锁
#include <stdio.h> #include <pthread.h> //1,定义互斥量 pthread_mutex_t m; int a=0,b=0; //线程共享进程的资源(a,b为全局变量),输出时两个线程同时操作,会导致if(a!=b)出错 void display() { //3.加锁 pthread_mutex_lock(&m); a++; b++; pthread_mutex_unlock(&m); //解锁 if(a!=b) { printf("%d!=%d\n",a,b); a=b=0; } } void *run1() { while(1) { display(); } } void *run2() { while(1) { display(); } } main() { pthread_t thid1, thid2; //2.初始化锁 pthread_mutex_init(&m,0); pthread_create(&thid1,NULL,(void*)run1,NULL); pthread_create(&thid2,NULL,(void*)run2,NULL); pthread_join(thid1,(void**)0); pthread_join(thid2,(void**)0); //4.释放互斥量 pthread_mutex_destroy(&m); }如果不使用互斥锁的话会输出两个明明相等的数不相等:
![](http://s3.51cto.com/wyfs02/M00/74/DC/wKiom1YsV5_ySNv5AAByyuQn-os438.jpg)
为了防止这种数据脏的问题,就需要使用互斥锁机制。
3.2死锁问题
在lock与unlock之间,调用pthread_exit或者在线程外部调用pthread_cancel会使其他线程被永久死锁。
pthread_exit退出线程,为了防止造成死锁,可以在pthread_exit语句前使用解锁语句unlock;
pthread_cancel退出线程,防止死锁可以使一对宏,这对宏类似于进程atexit函数:
void pthread_cleanup_push( void (*routine)(void *), //回调函数,routine指向处理函数 void *arg); //arg为传递给处理函数的参数 void pthread_cleanup_pop(int execute); //execute参数表示执行到pthread_cleanup_pop()时是否在弹出清理函数的同时执行该函数,为0表示不执行,非0为执行;这个参数并不影响异常终止时清理函数的执行。
push进去的函数可能在以下三个时机执行:
1,显示的调用pthread_exit();
2,在cancel点线程被cancel。
3,pthread_cleanup_pop()的参数不为0时。
例四:创建两个线程分别输出奇数和偶数
#include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t m; void *handle(void *d) { printf("退出后调用\n"); } void *runodd(void *d) { int i=0; for(i=1;;i+=2) { pthread_cleanup_push((void*)handle,0); pthread_mutex_lock(&m); printf("%d\n",i); pthread_mutex_unlock(&m); pthread_cleanup_pop(0); //如果设置为1,它会每次都调用清理函数,设置为0,只在死锁使执行清理函数 } } void *runeven(void *d) { int i=0; for(i=0;;i+=2) { pthread_mutex_lock(&m); printf("%d\n",i); pthread_mutex_unlock(&m); } } main() { pthread_t todd,teven; pthread_mutex_init(&m,0); pthread_create(&todd,0,runodd,0); pthread_create(&teven,0,runeven,0); sleep(5); pthread_cancel(todd); pthread_join(todd,(void**)0); pthread_join(teven,(void**)0); pthread_mutex_destroy(&m); }在线程代码加锁时,pthread_cancel会使线程在未解锁的情况下退出,从而导致另一个线程获得的所状态为0,一直处于阻塞状态,造成死锁;使用pthread_cleanup_push和pthread_cleanup_pop宏,就可以设置在出现死锁状态时要执行的清理函数,从而解决死锁。
相关文章推荐
- C#线程间不能调用剪切板的解决方法
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- C#停止线程的方法
- C#子线程更新UI控件的方法实例总结
- C#线程队列用法实例分析
- C++使用CriticalSection实现线程同步实例
- 基于C++实现的线程休眠代码
- VB读取线程、句柄及写入内存的API代码实例
- C#网络编程基础之进程和线程详解
- C#通过Semaphore类控制线程队列的方法
- C#多线程处理多个队列数据的方法
- C#实现线程安全的简易日志记录方法
- C#中线程同步对象的方法分析
- ASP.NET线程相关配置
- 浅析linux环境下一个进程最多能有多少个线程
- 再谈JavaScript线程
- C#实现终止正在执行的线程
- Java线程编程中的主线程讲解
- 解析Java线程同步锁的选择方法