Linux C编程之线程控制

        线程包含了表示进程执行环境所必要的信息,包括线程标识符,一组寄存器的值,栈,调度优先级和策略,信号屏蔽字,errno变量及线程私有数据,进程所有的信息对该进程内所有线程都是共享的,包括可执行程序文本,程序全局内存及堆内存,栈和文件描述符。在Linux创建新线程的时候,都会有一个控制线程用于控制新线程的相应工作,被称为主线程或控制线程。

        

目录

线程标识符:

 线程的属性:

线程控制相关函数:

线程之间的同步:

互斥锁:


线程标识符:

        与进程标识符类似,每一个线程都有一个线程标识符唯一表示,其用一个数据结构类型pthread_t来表示,Linux提供两个函数用于对线程标识符的操作:

#include <pthread.h>

pthread_t pthread_self(void);

 用于获取线程自身的线程标识符。

#include <pthread.h>

int pthread_equal(pthread_t tid1,pthread_t  tid2);

 两个参数分别是需要比较的线程标识符,相等返回一个非0值,否则返回0。

 线程的属性:

通过一个结构体pthread_attr_t来定义的:

typedef struct

{

int datachstate;    //线程拆卸状态

int schedpolicy;   //线程调度策略

struct sched_param schedparam;   //调度参数

int inheritsched;    //继承性

size_t guardsize;

int stzckaddr_set;   

void * stackaddr;   //堆栈位置

size_t stacksize;   //堆栈大小

}

pthread_attr_t;

线程控制相关函数:

#include <pthread.h>

int pthread_creat(pthread_t *thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg);

成功返回0,出错返回错误编号;

thread是返回的线程标识符,attr线程属性,一般设为NULL,start_routine线程运行的函数,arg是start_routine函数的参数。

creat_pthread.c如下:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

pthread_t ntid;

void prints(const char *s)
{
  pid_t pid;
  pthread_t tid;
  pid=getpid();
  tid=pthread_self();  //获取线程标识符
  printf("%s pid:%d  tid:%lu\n",s,pid,tid);
}
void* thread_fun(void* arg)
{
   prints("new thread:");
   return (void*)0;
}


int main()
{
   int err;
   err=pthread_create(&ntid,NULL,thread_fun,NULL);  //创建新线程
   if(err!=0)
		  {
				  printf("error : %s\n",strerror(err));
				  return -1;
		  }
   prints("main thread:");
   sleep(1);
   return 0;


}

用gcc编译时,有参数 -lpthread ,结果如下:

#include <pthread.h>

void pthread_exit(void * retval);

retval表示线程终止状态,可以由用户指定传递函数一个参数,pthread_exit执行完毕后调用该参数来获取线程退出 状态。

#include <pthread.h>

int pthread_join(pthread_t thread,void **reval);

成功返回0,出错返回非0.thread为线程标识符,用于指定要等待其终止的线程,reval存放其他线程的返回值。

join_thread.c如下:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>


void thread_fun(char *ptr)
{
int i;
for(i=0;i<5;i++)
{
   printf("%d--%s\n",i,ptr);
}

}

int main()
{ 
  void*reval;
  pthread_t tid1,tid2;
  char *ma1="this is first thread\n";
  char *ma2="this is second thread\n";
  pthread_create(&tid1,NULL,(void*)&thread_fun,(void*)ma1);
  pthread_create(&tid2,NULL,(void*)&thread_fun,(void*)ma2);
  pthread_join(tid1,&reval);
  pthread_join(tid2,&reval);

return 0;
}


主线程等待创建的两个新线程执行完毕后才会结束。结果如下:

#include <pthread.h>

int pthread_cancel(pthread_t thread);

成功返回0,出错返回错误编号。thread要取消线程的标识符。用于同一进程内取消另一个线程运行。当调用该函数取消一个线程之后,需要调用相应的函数对进程退出之后的环境进行清理,这些函数被称为线程清理处理程序,函数原型如下:

 #include <pthread.h>

void pthread_cleanup_push(void (*routine)(void*),void*arg);

void pthread_cleanup_pop(int excute);

pthread_cleanup_push函数将子程序 routine和参数arg压入当前线程处理程序的堆栈,在当前线程调用pthread_exit或者通过pthread_cancel终止执行时,堆栈中处理程序将按照压栈时相反的顺序依次调用;

pthread_cleanup_pop函数从线程处理程序中弹出栈顶的程序并执行它。

在linux中,线程一般有分离和非分离两种状态,默认是非分离的,父线程维护子线程的某些信息并等待子线程结束,如果没用join情形下,子线程结束时,父线程维护的信息可能没来得及释放。而分离线程,不会有其他线程等待他结束,它运行结束后,线程终止,资源得到释放,可以调用pthread_detach函数实现分离线程。

 #include <pthread.h>

int pthread_detach(pthread_t thread);

线程之间的同步:

互斥锁:

  为实现多个线程并发执行时互斥和同步访问共享资源时,采用的一种机制,如果一个线程已经锁定了一个互斥锁,其他线程会被挂起等待。

#include <pthread.h>

int pthread_mutex_init (pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);

成功返回0,失败返回错误编号。该函数函数初始化互斥锁,参数mutex是函数返回的指向互斥锁变量,mutexattr互斥锁属性,可以设置为NULL。

#include <pthread.h>

int pthread_mutex_destroy(pthread_mutex_t *mutex)

成功返回0,失败返回错误编号,该函数用来注销一个互斥锁。

 #include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);

成功返回0,出错返回非零值,用pthread_mutex_lock()加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会阻塞,直到互斥锁被其他线程释放。当pthread_mutex_lock()函数返回时,说明互斥锁已经被当前线程成功加锁。pthread_mutex_trylock函数则不同,如果mutex已经被加锁,他将立即返回,返回的错误码为ebusy,而不是阻塞等待。两者对已加锁的处理不同。

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex)

 成功返回0,出错返回非零值,该函数用于解锁参数mutex指向的互斥锁。

如下,实现两个线程之间同步操作:lock_thread.c

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>

char buffer[256];
pthread_mutex_t mutex;
int retflag=0;
int buin=0;

void thread_fun();

int main()
{
 pthread_t tid;
 pthread_mutex_init(&mutex,NULL);    
 pthread_create(&tid,NULL,(void*)&thread_fun,NULL);
  
 int i=0;
 while(1)
 {
   if(i==5)
   {
     retflag=1;
     return 0;
   }
     pthread_mutex_lock(&mutex);
     if(buin==0)
     {
     sprintf(buffer,"this is %d\n",i++);
     buin=1;
     }

     pthread_mutex_unlock(&mutex);
 }

return 0;
}

void thread_fun()
{
   while(1)
   {
      if(retflag)
       return ;
       
       pthread_mutex_lock(&mutex);
       if(buin==1)
       {
       buin=0;
       printf("%s",buffer);
       }
       pthread_mutex_unlock(&mutex);
   }
   return;
   
}


上述代码主线程向buffer写入数据,新线程读取打印数据,为保证同步操作,采用互斥锁使得buffer同一时间只能被一个线程访问,防止出现为写入数据就被读取的情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值