linux多线程

来源:互联网 发布:淘宝会员名怎么更改 编辑:程序博客网 时间:2024/06/03 09:00
线程标识:
就像每个进程都有一个ID一样,线程也有自己的ID。
    进程ID用pid_t来表示,他是一个unsigned int。
    进程ID用pthread_t来表示,pthread_t不能把它当整数处理。
    进程可以通过pthread_self()函数获得自身的线程ID。

线程创建:
  在进程中只有一个控制线程
    程序开始运行的时候每个进程只有一个线程,他是以单线程方式启动的,在创建多个线程以前,进程的行为与传统的进程没有区别。
    gcc在链接的时候需要添加-lpthread选项
    创建一个线程调用pthread_create函数。
    
    #include<pthread.h>
    int pthread_creatc(pthread_t *thread,const pthread _attr_t *attr,void *(*start_routine)(void *),void *arg);
   若线程创建成功,则返回0。若线程创建失败,则返回出错编号,并且*thread中的内容是未定义的。
    返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于指定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。


linux下用C语言开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。


由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。


参数
第一个参数为指向线程标识符的指针。


第二个参数用来设置线程属性。


第三个参数是线程运行函数的起始地址。


最后一个参数是运行函数的参数。


注意事项
因为pthread并非Linux系统的默认库,而是POSIX线程库。在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。函数在执行错误时的错误信息将作为返回值返回,并不修改系统全局变量errno,当然也无法使用perror()打印错误信息。


线程终止:
    任一线程调用了exit函数,整个进程都会终止。
    如果信号默认动作是终止进程,那么信号发送到该线程,整个进程也会被终止。
    单个线程通过以下三种方式退出:
线程只是从启动函数中返回,返回值是线程的退出码。
线程可以被同一进程中的其他线程取消。
线程调用pthread_exit。

    
关闭本线程
    void pthread_exit(void *arg);
arg是个无类型指针,该指针会被其他线程调用
  也就是返回值
关闭其他线程
    int thread_cancel(pthread_t th);


挂起线程:
    pthread_join(pthread_t th,void **the_return);




    挂起当前线程,直至th指定的线程终止为止。
    如果另一个线程返回值不是NULL,则保存thr_return地址中。
    一个地址所使用的内存资源应用pthread_join调用之前不会被重新分配,所以对于每个线程必须调用一次pthread_join函数。
    其他线程不能对同一线程再应用pthread_join调用。

线程分离:
    int pthread_detach(pthread_t th);
    pthread_detach函数使线程处于被分离状态。
    对于被分离状态的线程,不需要调用pthread_join,如果其他线程调用pthread_join失败,返回EINVAI
    如果不等待一个线程,同时对线程的返回值不感兴趣,可以设置这个线程为被分离状态,让系统在线程退出的时候自动回收他所占用的资源。
    一个线程不能自己调用pthread_detach改变自己为被分离的状态,只能由其他线程调用pthread_detach。


判断是否为同一条线程:
    int pthread_equal(pthread_t th1,pthread_t th2);函数比较th1和th2是否为同一个线程,所以不能用比较整数的方式比较pthread_t。
    如果th1和th2相同,函数返回非0值,如果不同函数返回0.


线程属性:


    以前调用pthread_create传入的attr参数都是空指针,而不是指向pthread_attr_t结构的指针。
    可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来。
    可以使用pthread_attr_init函数初始化pthread_attr_t结构。
    调用pthread_attr_init以后,pthread_arrt_t的结构所包含的内容就是操作系统实现支持多线程所有的属性的默认值。 如果要修改其中个别属性的值需要调用其他函数。
    






    int pthread_attr_destroy(pthread_attr_t *attr);
    int pthread_attr_init(pthread_attr_t *attr);


函数pthread_attr_init初始化attr结构
函数pthread_attr_destroy()释放attr内存空间




pthread_attr_t的结构对于应用程序来讲是不透明的,应用程序不需要了解有关结构的内部组成。
     




    int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
  函数pthread_attr_setdetachstate把线程属性设置为下面两个合法值之一


PTHREAD_CREATE_DETACHED 设置线程为分离状态
PTHREAD_CREATE_JOINABLE  设置线程为正常状态

原子操作:
    i++


mov eax,i
add eax,1




计算机每次只执行一句汇编代码,而c++代码大多都不是原子操作

线程同步:
  线程共享进程的内存空间,打开的文件描述符,全局变量。
    当有多个线程同时访问一块内存空间或者一个变量。一个文件描述符,如果不加控制,那么可能会出现意想不到的结果。
    互斥(mutex)是相互排斥的意思,它是一种锁或者信号灯。
  互斥用来保护多个线程共享的数据和结构不会被同时修改,一个互斥锁只能有两个状态
   ---locked---加锁
   ---unlocked-解锁
  


   加锁后互斥不让其他线程访问。
   任何时刻只能有一个线程来掌握某个互斥上锁。
   一个线程如果试图在一个已经加锁的互斥上再加锁,这个线程会被挂起,知道加锁的线程释放掉所有的互斥锁为止。


  pthread_mutex_t mutex=PTHREAD_MUTEX_INITALIZER;
  int pthread_mutex_lock(pthread_mutex_t *mutex);
  int pthread_mutex_unlock(pthread_mutex_t *mutex);


 PTHREAD_MUTEX_INITIALZER是初始化一个快速缩的宏定义。
 pthread_mutex_lock用于给mutex加锁
 pthread_mutex_unlock用于给mutex解锁。




pthread_mutex_unlock()
 加锁返回0  没加锁返回错误值






当有一个线程未解锁的时候被结束会出现死锁!!!!
原子锁实现多线程同步代码:
  #include <stdio.h>     #include <unistd.h>    #include <errno.h>    #include <pthread.h>pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;void pr(void *p){    int i=*(int *)p;    int j=0;    pthread_mutex_lock(&mutex);    for(;j<10;j++)    {    printf("%d\n",i);    sleep(1);    }    pthread_mutex_unlock(&mutex);}int main(){    int i[2];    i[0]=1;    i[1]=2;    pthread_t thread1,thread2;    if(pthread_create(&thread1,NULL,pr,&i[0])=!0);    {    printf("errno is %s\n",strerror(errno));    }    if(pthread_create(&thread2,NULL,pr,&i[1])!=0);    {    printf("errno is %s\n",strerror(errno));    }    pthread_join(thread1,NULL);    pthread_join(thread1,NULL);}


多线程参数传递小窍门:

  传递单个参数  传递变量地址
    需要传递多个参数 可以传递结构体(指针)

0 0
原创粉丝点击