zoukankan      html  css  js  c++  java
  • pthread_create,pthread_once,pthread_key_create,pthread_key_delete,pthread_getspecific,pthread_setspecific()

    pthread_create是UNIX环境创建线程函数

    头文件

      #include<pthread.h>

    函数声明

      int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);

    返回值

      若成功则返回0,否则返回出错编号

      返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。

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

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

    参数

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

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

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

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

      另外,在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库

    示例

      打印线程 IDs

      #include <pthread.h>

      #include <stdlib.h>

      #include <stdio.h>

      #include <unistd.h>

      #include <string.h>

      pthread_t ntid;

      void printids(const char *s)

      {

      pid_t pid;

      pthread_t tid;

      pid = getpid();

      tid = pthread_self();

      printf("%s pid %u tid %u (0x%x) ", s,

      (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);

      }

    void *thr_fn(void *arg)

      {

      printids("new thread: ");

      return((void *)0);

      }

      int main(void)

      {

      int err;

      err = pthread_create(&ntid, NULL, thr_fn, NULL); 

      if (err != 0)

      printf("can't create thread: %s ", strerror(err));

      printids("main thread:");

      sleep(1);

      exit(0);

      }

      $ gcc main.c -lpthread

      $ ./a.out

    向线程函数传递参数详解:

    向线程函数传递参数分为两种:

    (1)线程函数只有一个参数的情况:直接定义一个变量通过应用传给线程函数。

    例子:

    #include <iostream>
    #include <pthread.h>
    using namespace std;
    pthread_t thread;
    void fn(void *arg)
    {
        int i = *(int *)arg;
        cout<<"i = "<<i<<endl;
        return ((void *)0);
    }
    int main()
    {
        int err1;
        int i=10;
       err1 = pthread_create(&thread, NULL, fn, &i);
        pthread_join(thread, NULL);
    }
    2、线程函数有多个参数的情况:这种情况就必须申明一个结构体来包含所有的参数,然后在传入线程函数,具体如下:

    例子:

    首先定义一个结构体:

    struct  parameter

    {

      int size,

      int count;

    。。。。。

    。。。 
    };

    然后在main函数将这个结构体指针,作为void *形参的实际参数传递

    struct parameter arg;

    通过如下的方式来调用函数:
    pthread_create(&ntid, NULL, fn,& (arg));
    函数中需要定义一个parameter类型的结构指针来引用这个参数 

    void fn(void *arg)
    {
        int i = *(int *)arg;
        cout<<"i = "<<i<<endl;
        return ((void *)0);
    }

    void thr_fn(void *arg)
    {
           struct parameter *pstru;
           pstru = ( struct parameter *) arg;
           然后在这个函数中就可以使用指针来使用相应的变量的值了。
    }

    int pthread_once(pthread_once_t *once_control, void (*init_routine) (void))

    本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。

    #include <pthread.h>

    int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));创建线程私有数据

    int pthread_key_delete(pthread_key_t key);注销线程私有数据

    说明:

    函数 pthread_key_create() 用来创建线程私有数据。该函数从 TSD 池中分配一项,将其地址值赋给 key 供以后访问使用。第 2 个参数是一个销毁函数,它是可选的,可以为 NULL,为 NULL 时,则系统调用默认的销毁函数进行相关的数据注销。如果不为空,则在线程退出时(调用 pthread_exit() 函数)时将以 key 锁关联的数据作为参数调用它,以释放分配的缓冲区,或是关闭文件流等。

    不论哪个线程调用了 pthread_key_create(),所创建的 key 都是所有线程可以访问的,但各个线程可以根据自己的需要往 key 中填入不同的值,相当于提供了一个同名而不同值的全局变量(这个全局变量相对于拥有这个变量的线程来说)。

    注销一个 TSD 使用 pthread_key_delete() 函数。该函数并不检查当前是否有线程正在使用该 TSD,也不会调用清理函数(destructor function),而只是将 TSD 释放以供下一次调用 pthread_key_create() 使用。在 LinuxThread 中,它还会将与之相关的线程数据项设置为 NULL。

    void *pthread_getspecific(pthread_key_t key);读线程私有数据

    int pthread_setspecific(pthread_key_t key, const void *value);写线程私有数据

    函数 pthread_setspecific() 将 pointer 的值 (不是锁指的内容) 与key 相关联。

    函数 pthread_getspecific() 将与 key 相关联的数据读出来。返回的数据类型都是 void *,因此可以指向任何类型的数据。

  • 相关阅读:
    BZOJ 1036:树的统计Count(树链剖分)
    HDU 5950:Recursive sequence(矩阵快速幂)
    POJ 2763:Housewife Wind(树链剖分)
    HDU 2222:Keywords Search(AC自动机模板)
    HDU 3966:Aragorn's Story(树链剖分)
    矩阵乘法
    HDU 4635:Strongly connected(强连通)
    HDU 3078:Network(LCA之tarjan)
    HDU 2767:Proving Equivalences(强连通)
    HDU 1827:Summer Holiday(强连通)
  • 原文地址:https://www.cnblogs.com/myyan/p/4791123.html
Copyright © 2011-2022 走看看