线程概念及其在Linux中的应用。

一。线程基本概念

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 }

以上就是线程的全部内容了。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值