发布时间:2014-09-05 17:07:01作者:知识屋
Linux多线程
1.线程概述
线程是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。一个进程可以有多个线程,也就
是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。
2.线程实现
线程创建pthread_create()
所需头文件#include <pthread.h>
函数原型int pthread_create ((pthread_t *thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg))
thread:线程标识符
attr:线程属性设置
start_routine:线程函数的起始地址
arg:传递给start_routine的参数
函数返回值 成功:0 出错:-1
线程退出pthread_exit();
所需头文件#include <pthread.h>
函数原型void pthread_exit(void *retval)
函数传入值retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_join 来检索获取
等待线程退出并释放资源pthread_join()
所需头文件#include <pthread.h>
函数原型int pthread_join ((pthread_t th, void **thread_return))
函数传入值
th:等待线程的标识符
thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
函数返回值 成功:0 出错:-1
代码举例
1. #include<pthread.h>
2. #include<stdio.h>
3. #include<errno.h>
4.
5. /*线程1*/
6. void thread1()
7. {
8. int i=0;
9.
10. while(1)
11. {
12. printf("thread1:%d/n",i);
13. if(i>3)
14. pthread_exit(0);
15. i++;
16. sleep(1);
17. }
18. }
19.
20. /*线程2*/
21. void thread2()
22. {
23. int i=0;
24.
25. while(1)
26. {
27. printf("thread2:%d/n",i);
28. if(i>5)
29. pthread_exit(0);
30. i++;
31. sleep(1);
32. }
33. }
34.
35. int main()
36. {
37. pthread_t t1,t2;
38.
39. /*创建线程*/
40. pthread_create(&t1,NULL,(void *)thread1,NULL);
41. pthread_create(&t2,NULL,(void *)thread2,NULL);
42. /*等待线程退出*/
43. pthread_join(t1,NULL);
44. pthread_join(t2,NULL);
45. return 0;
46. }
3同步与互斥
<1>互斥锁
互斥锁的操作主要包括以下几个步骤。
• 互斥锁初始化:pthread_mutex_init
• 互斥锁上锁:pthread_mutex_lock
• 互斥锁判断上锁:pthread_mutex_trylock
• 互斥锁接锁:pthread_mutex_unlock
• 消除互斥锁:pthread_mutex_destroy
1. #include<pthread.h>
2. #include<stdio.h>
3. #include<errno.h>
4.
5. int i=0;/*共享变量*/
6. pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;/*互斥锁*/
7.
8. void thread1()
9. {
10. int ret;
11. while(1)
12. {
13.
14.
15. ret=pthread_mutex_trylock(&mutex);/*判断上锁*/
16.
17. if(ret!=EBUSY)
18. {
19. pthread_mutex_lock(&mutex);/*上锁*/
20. printf("This is thread1:%d/n",i);
21. i++;
22. pthread_mutex_unlock(&mutex);/*解锁*/
23. }
24. sleep(1);
25. }
26. }
27.
28. void thread2()
29. {int ret;
30. while(1)
31. {
32.
33. ret=pthread_mutex_trylock(&mutex);
34. if(ret!=EBUSY)
35. {
36. pthread_mutex_lock(&mutex);
37. printf("This is thread2:%d/n",i);
38. i++;
39. pthread_mutex_unlock(&mutex);
40. }
41. sleep(1);
42. }
43. }
44. int main()
45. {
46. pthread_t t1,t2;
47. pthread_mutex_init(&mutex,NULL);
48. pthread_create(&t1,NULL,(void *)thread1,NULL);
49. pthread_create(&t2,NULL,(void *)thread2,NULL);
50.
51. pthread_join(t1,NULL);
52. pthread_join(t2,NULL);
53.
54. pthread_mutex_destroy(&mutex);
55. return 0;
56. }
<2>信号量
未进行同步处理的两个线程
1. #include<pthread.h>
2. #include<stdio.h>
3. #include<errno.h>
4.
5. int i=0;
6. void thread1()
7. {
8.
9. while(1)
10. {
11. printf("This is thread1:%d/n",i);
12. i++;
13. sleep(1);
14. }
15. }
16.
17.
18. void thread2()
19. {
20.
21. while(1)
22. {
23. printf("This is thread2:%d/n",i);
24. i++;
25. sleep(1);
26. }
27. }
28.
29. int main()
30. {
31. pthread_t t1,t2;
32.
33. pthread_create(&t1,NULL,(void *)thread1,NULL);
34. pthread_create(&t2,NULL,(void *)thread2,NULL);
35.
36. pthread_join(t1,NULL);
37. pthread_join(t2,NULL);
38.
39. return 0;
40. }
执行结果如下:
This is thread1:0
This is thread2:1
This is thread2:2
This is thread1:3
This is thread2:4
This is thread1:4
This is thread2:6
This is thread1:7
......
可以看出:
1.线程2的执行并非必须在线程1之后,如果要求线程2必须在线程1之后执行,称为同步
2.线程1和线程2可能对共享变量i的同时进行读取,如果要求每次只有一个线程读取i,成为互斥
信号量的使用
•sem_init用于创建一个信号量,并能初始化它的值。
•sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在于若信号量小于零时, sem_wait将会阻塞进程,而sem_trywait则会立即返回。
•sem_post相当于V操作,它将信号量的值加一同时发出信号唤醒等待的进程。
•sem_getvalue用于得到信号量的值。
•sem_destroy用于删除信号量
代码
1. #include<pthread.h>
2. #include<stdio.h>
3. #include<errno.h>
4. #include <semaphore.h>
5.
6.
7. int i=0;
8. sem_t sem1,sem2;
9.
10.
11. void thread1()
12. {
13.
14. while(1)
15. {
16. sem_wait(&sem1);
17. printf("This is thread1:%d/n",i);
18. i++;
19. sleep(3);/*线程1休眠3s,以便观察线程2在输出3s后才会执行*/
20. sem_post(&sem2);
21.
22. }
23. }
24.
25.
26. void thread2()
27. {
28.
29. while(1)
30. {
31. sem_wait(&sem2);
32. printf("This is thread2:%d/n",i);
33. i++;
34. sem_post(&sem1);
35. sleep(1);
36. }
37. }
38.
39. int main()
40. {
41. pthread_t t1,t2;
42.
43.
44.
45. sem_init(&sem1,0,1);/*初始化信号量sem1*/
46. sem_init(&sem2,0,0);
47.
48. pthread_create(&t1,NULL,(void *)thread1,NULL);
49. pthread_create(&t2,NULL,(void *)thread2,NULL);
50.
51. pthread_join(t1,NULL);
52. pthread_join(t2,NULL);
53.
54. return 0;
55. }
1. #include<pthread.h>
2. #include<stdio.h>
3. #include<errno.h>
4. #include <semaphore.h>
5.
6.
7. int i=0;
8. sem_t sem;
9.
10.
11. void thread1()
12. {
13.
14. while(1)
15. {
16. sem_wait(&sem);
17. printf("This is thread1:%d/n",i);
18. i++;
19. sleep(3);/*线程1休眠3s,以便观察线程2在输出3s后才会执行*/
20. sem_post(&sem);
21.
22. }
23. }
24.
25.
26. void thread2()
27. {
28.
29. while(1)
30. {
31. sem_wait(&sem);
32. printf("This is thread2:%d/n",i);
33. i++;
34. sem_post(&sem);
35. sleep(1);
36. }
37. }
38.
39. int main()
40. {
41. pthread_t t1,t2;
42.
43.
44.
45. sem_init(&sem,0,1);/*初始化信号量sem*/
46.
47. pthread_create(&t1,NULL,(void *)thread1,NULL);
48. pthread_create(&t2,NULL,(void *)thread2,NULL);
49.
50. pthread_join(t1,NULL);
51. pthread_join(t2,NULL);
52.
53. return 0;
54. }
linux一键安装web环境全攻略 在linux系统中怎么一键安装web环境方法
Linux网络基本网络配置方法介绍 如何配置Linux系统的网络方法
Linux下DNS服务器搭建详解 Linux下搭建DNS服务器和配置文件
对Linux进行详细的性能监控的方法 Linux 系统性能监控命令详解
linux系统root密码忘了怎么办 linux忘记root密码后找回密码的方法
Linux基本命令有哪些 Linux系统常用操作命令有哪些
Linux必学的网络操作命令 linux网络操作相关命令汇总
linux系统从入侵到提权的详细过程 linux入侵提权服务器方法技巧
linux系统怎么用命令切换用户登录 Linux切换用户的命令是什么
在linux中添加普通新用户登录 如何在Linux中添加一个新的用户
2012-07-10
CentOS 6.3安装(详细图解教程)
Linux怎么查看网卡驱动?Linux下查看网卡的驱动程序
centos修改主机名命令
Ubuntu或UbuntuKyKin14.04Unity桌面风格与Gnome桌面风格的切换
FEDORA 17中设置TIGERVNC远程访问
StartOS 5.0相关介绍,新型的Linux系统!
解决vSphere Client登录linux版vCenter失败
LINUX最新提权 Exploits Linux Kernel <= 2.6.37
nginx在网站中的7层转发功能