一。线程基本概念
1.首先线程就是一个程序里的执行路线。在Linux中,因为没有专门描述它的东西,所以又称它为轻量级进程。
2.线程与进程的联系与区别:
(1)进程有独立的地址空间,而线程是共享进程地址空间的,它没有独立的地址空间。
(2)进程是操作系统分配资源的基本单位,线程是操作系统CPU调度的一个基本单位。
(3)进程和线程还共享着文件描述符、组ID、信号处理方式以及当前工作目录。
(4)但线程也有自己的ID、上下文数据、栈、调度优先级以及自己的错误信号。
(5)多进程很稳定,但是多线程不稳定。
3.线程的优缺点:
优点:
(1)创建线程比创建进程要简单方便得多,而且线程所占的资源也比进程少很多。
(2)线程之间的切换也比进程间切换方便的多。
(3)能充分地利用多处理器的并发应用。
缺点:
(1)性能损失较大。
(2)缺乏访问控制。
(3)缺乏保护。
(4)编程难度的提高。
二。线程控制
1.线程创建:
int pthread_create(pthread_t *thread, //id。
const pthread_attr_t *arrt, //线程属性,一般为NULL。
void *(*start_routine)(void*), //函数指针。
void *arg); //传递给该函数的传参。
应用实例:
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<pthread.h>
4 #include<stdlib.h>
5
6 void* thr_start(void *arg)
7 {
8 while(1){
9 printf("i am a thread!\n");
10 sleep(1);
11 }
12 }
13 int main()
14 {
15 pthread_t tid=0;
16 tid=pthread_create(&tid,NULL,thr_start,NULL);
17 if(tid==-1){
18 perror("tid");
19 exit(1);
20 }
21 while(1)
22 {
23 printf("I am the main thread!\n");
24 sleep(1);
25 }
26 return 0;
27 }
可以通过命令查看线程已经创建了:
[ymk@localhost day14]$ ps -ef | grep pthread
ymk 4297 3974 0 02:04 pts/2 00:00:00 ./pthread
三。线程终止
1.首先终止一个线程有三种基本方法:
(1)主函数中的return返回退出。
(2)exit;退出。
(3)pthread_exit(void **retval);退出。
2.同时还有一个取消线程:pthread_cancel(pthread_t thread);
3.退出线程还要注意一些问题:
(1)退出线程可以使用return,但是在主线程中不能使用,在主线程中return,相当于退出整个进程.
(2)线程退出后,如果是joinable状态,则不会自动释放资源,需要其他线程使用pthread_join接口 来等待线程退出,并获取返回值,释放资源。
(3)线程被分离后,那么这个线程退出时候,自动释放资源,不需被等待。
(4)当一个线程被分离之后,那么这个线程是无法被pthread_joid等待的,否则返回EINVAL错误。
应用:为了方便,这里就不写头文件了
(1)用return退出:
6 void* thr_start(void *arg)
7 {
8 while(1){
9 printf("i am a thread!\n");
10 sleep(1);
11 }
12 }
13 int main()
14 {
15 pthread_t tid=0;
16 tid=pthread_create(&tid,NULL,thr_start,NULL);
17 if(tid==-1){
18 perror("tid");
19 exit(1);
20 }
21 while(1)
22 {
23 printf("I am the main thread!\n");
24 sleep(1);
25 return 0;
26 }
27 return 0;
28 }
结果是:打印之后一秒自动退出。
[ymk@localhost d2]$ ./exit
I am the main thread!
i am a thread!
分析:在主函数中使用return就会让整个进程退出,所以其他线程也就不能运行了。但是若在其它线程内用return,只会退出当前线程,主线程还会继续运行。
(2)用exit退出。
代码如上:就是用exit代替return。在主线程用时,程序打印一次之后自动退出,在其它线程应用时,会多打印一次主线程,然后退出。
(3)用pthread——exit退出。
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<pthread.h>
4 #include<stdlib.h>
5
6 void* thr_start(void *arg)
7 {
8 while(1){
9 printf("i am a thread!\n");
10 sleep(1);
11 }
12 }
13 int main()
14 {
15 pthread_t tid=0;
16 tid=pthread_create(&tid,NULL,thr_start,NULL);
17 if(tid==-1){
18 perror("tid");
19 exit(1);
20 }
21 while(1)
22 {
23 printf("I am the main thread!\n");
24 sleep(1);
25 pthread_exit(NULL);
26
27 }
28 return 0;
29 }
结果:
[ymk@localhost d2]$ ./exit
I am the main thread!
i am a thread!
i am a thread!
i am a thread!
i am a thread!
i am a thread!
在主线程中用,只退出主线程,其它线程可以继续执行,这就是它和return的区别。
四。线程等待
1.//线程等待:
int pthread_join(pthread_t thread,
void **retval);
2.应用:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5
6 void *thread_start(void *arg)
7 {
8 sleep(4);
9 printf("new thread,thread is : %u,pid,%d\n",pthread_self(),getpid()); return (void *)123;
10 }
11
12 int main(void)
13 {
14 void *ret;
15 pthread_t tid;
16 pthread_create(&tid,NULL,thread_start,NULL);
17 pthread_join(tid,&ret);
18 printf("join new thread success, ret: %d\n",(int)ret);
19 }
结果:
[ymk@localhost d8]$ ./pthread1
new thread,thread is : 1244657408,pid,5536
join new thread success, ret: 123
五。线程间的互斥与同步
1.死锁产生的四个必要条件:
(1)互斥条件。
(2)不可剥夺条件。
(3)请求与保持条件。
(4)环路等待条件。
(5)预防死锁方法:银行家算法:安全状态和非安全状态。
2.第一个锁:互斥锁:mutex.
应用:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5 int ticket=100;
6 pthread_mutex_t mutex;
7 void *thr_start(void *arg)
8 {
9 int id=(int )arg;
10 printf("thread:%d\n",id);
11 while(1){
12 pthread_mutex_lock(&mutex);
13 if(ticket>0){
14 usleep(10000);
15 ticket--;
16 printf("thread: %d get a ticket,ticket:%d\n",id,tick et);
17 }
18 pthread_mutex_unlock(&mutex);
19 }
20 return NULL;
21 }
22
23 int main()
24 {
25 pthread_t tid;
26 int ret;
27 int i=0;
28 pthread_mutex_init(&mutex,NULL);
29 for(i=0;i<4;i++){
30 ret=pthread_create(&tid,NULL,thr_start,(void *)i);
31 if(ret!=0){
32 printf("pthread_create error!\n");
33 return -1;
34 }
35 }
36 pthread_join(tid,NULL);
37 pthread_mutex_destroy(&mutex);
38 return 0;
39 }
3.第二个锁:条件变量:cond.
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5
6 int noodels=0;
7 pthread_cond_t cond;
8 pthread_mutex_t mutex;
9 void* thr_sell(void *arg)
10 {
11 while(1){
12 pthread_mutex_lock(&mutex);
13 if(noodels==0){
14 printf("producer put noodels\n");
15 noodels=1;
16 sleep(1);
17 pthread_cond_signal(&cond);
18 }
19 pthread_mutex_unlock(&mutex);
20 }
21 return NULL;
22 }
23 void* thr_buy(void *arg)
24 {
25 while(1){
26 pthread_mutex_lock(&mutex);
27 while(noodels==0){
28 pthread_mutex_unlock(&mutex);
29 pthread_cond_wait(&cond,&mutex);
30 }
31 printf("delicious!\n");
32 noodels=0;
33 pthread_mutex_unlock(&mutex);
34 }
35 return NULL;
36 }
37 int main()
38 {
39 pthread_t tid1,tid2;
40 pthread_cond_init(&cond,NULL);
41 pthread_mutex_init(&mutex,NULL);
42 int ret;
43 ret=pthread_create(&tid1,NULL,thr_sell,NULL);
44 if(ret!=0){
45 printf("pthread_creat error\n");
46 return -1;
47 }
48 ret=pthread_create(&tid2,NULL,thr_buy,NULL);
49 if(ret!=0){
50 printf("pthread_creat error\n");
51 return -1;
52 }
53 pthread_join(tid1,NULL);
54 pthread_join(tid2,NULL);
55 pthread_cond_destroy(&cond);
56 pthread_mutex_destroy(&mutex);
57
58 return 0;
59 }
4.第三个锁:POSIX信号量:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5 #include<semaphore.h>
6
7 sem_t sem_pro;
8 sem_t sem_con;
9
10 void *thr_producer(void *arg)
11 {
12 while(1){
13 sem_wait(&sem_pro);
14 printf("producer put noodeles!\n");
15 sleep(1);
16 sem_post(&sem_con);
17 }
18 }
19 void *thr_consumer(void *arg)
20 {
21 while(1){
22 sem_wait(&sem_con);
23 printf("consumer eat noodeles!\n");
24 sem_post(&sem_pro);
25 }
26 }
27
28 int main()
29 {
30 pthread_t tid1,tid2;
31 int ret;
32 sem_init(&sem_pro,0,0);
33 sem_init(&sem_con,0,1);
34 ret=pthread_create(&tid1,NULL,thr_producer,NULL);
35 if(ret!=0)
36 {
37 printf("pthread create error!\n");
38 return -1;
39 }
40 ret=pthread_create(&tid2,NULL,thr_consumer,NULL);
41 if(ret!=0)
42 {
43 printf("pthread create error!\n");
44 return -1;
45 }
46 pthread_join(tid1,NULL);
47 pthread_join(tid2,NULL);
48
49 sem_destroy(&sem_pro);
50 sem_destroy(&sem_con);
51 return 0;
52 }
5.还有一些其他的锁,比如:读写锁,自旋锁。
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<pthread.h>
4 #include<unistd.h>
5
6 char *ptr="i am a blackboard";
7 pthread_rwlock_t rwlock;
8
9 void* thr_write(void* arg)
10 {
11 pthread_t tid=pthread_self();
12 while(1){
13 pthread_rwlock_wrlock(&rwlock);
14 printf("write thread:%p %s\n",tid,ptr);
15 sleep(1);
16 printf("write thread:%p,beautiful\n",tid);
17 pthread_rwlock_unlock(&rwlock);
18 usleep(100);
19 }
20 return NULL;
21 }
22 void* thr_read(void* arg)
23 {
24 pthread_t tid=pthread_self();
25 while(1){
26 pthread_rwlock_rdlock(&rwlock);
27 printf("read thread:%p it is beautiful!\n",tid);
28 sleep(1);
29 printf("read thread:%p it is beautiful!\n",tid);
30 pthread_rwlock_unlock(&rwlock);
31 sleep(1);
32 }
33 }
34 int main()
35 {
36 pthread_t tid1[2],tid2[2];
37 pthread_rwlock_init(&rwlock,NULL);
38 pthread_create(&tid1[0],NULL,thr_write,NULL);
39 pthread_create(&tid1[1],NULL,thr_write,NULL);
40 pthread_create(&tid2[0],NULL,thr_read,NULL);
41 pthread_create(&tid2[1],NULL,thr_read,NULL);
42
43 pthread_join(tid1[0],NULL);
44 pthread_join(tid1[1],NULL);
45 pthread_join(tid2[0],NULL);
46 pthread_join(tid2[1],NULL);
47 pthread_rwlock_destroy(&rwlock);
48 return 0;
49 }
这些锁都是通过让这个线程在同一时间只能被一个访问,其它都得等待。
六。守护进程:
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4 #include<string.h>
5 void pdaemon()
6 {
7 int pid=-1;
8 umask(0);
9 pid=fork();
10 if(pid>0)
11 {
12 exit(0);
13 }
14 else if(pid<0){
15 exit(-1);
16 }
17 if(setsid()<0){
18 exit(-1);
19 }
20 chdir("/");
21 if(pid>0){
22 exit(0);
23 }
24 else if(pid<0){
25 exit(-1);
26 }
27 close(0);
28 close(1);
29 close(2);
30 }
31
32
33
34 int main()
35 {
36 pdaemon();
37 while(1){
38 sleep(1);
39 }
40 }
以上就是线程的全部内容了。