Posix Threads API 整理

定义:

并发与并行:

  • 并发(concurrency):实际上串行发生的事情好像同时发生,表述了单核处理器中线程或者进程的行为特点
  • 并行(parallelism):并发序列同时执行, 真正的并行只能在多处理其上存在。

异步与同步:

       异步(asynchronous)与同步(synchronous)区别在于发需求的人是否需要等到需要完成才可以执行其他事情。

线程安全和可重入:

  •   线程安全:能够被多个线程调用而不会产生灾难性结果,大部分函数可以利用互斥量,条件变量,线程私有数据实现线程安全。 
  •   可重入:采用比将函数和库转换为一系列更为复杂方式使得代码成为线程安全。可重入函数应该避免任何静态数据和共享全局数据,避免依赖线程间任何形式的同步。

 

数据类型:

线程相关数据类型

类型描述
pthread_t线程标识符
pthread_mutex_t互斥量
pthread_spinlock_t 自旋锁
pthread_cond_t条件变量
pthread_key_t线程私有数据访问键
pthread_attr_t线程属性对象
pthread_mutexattr_t互斥量属性对象
pthread_rwlockattr_t 读写锁属性
pthread_condattr_t条件变量属性对象
pthread_once_t一次性初始化属性对象
sigevent线程通知机制

 

线程POSIX API:

基本操作

建立与终止 pthread_create  
pthread_exit 
等待 pthread_join 
取消 pthread_cancel 
 线程分离 pthread_detach 
 获取线程标识符 pthread_self
比较线程标识符 pthread_equal 

    基本操作 example

//线程创建

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
void *
thread (void *arg)
{
  char *ret;
  printf ("thread() entered with argument '%s'\n", arg);
  if ((ret = (char *) malloc (20)) == NULL)
    {
      perror ("malloc() error");
      exit (2);
    }
  strcpy (ret, "This is a test");
  pthread_exit (ret);
}

main ()
{
  pthread_t thid;
  void *ret;

  if (pthread_create (&thid, NULL, thread, "thread 1") != 0)
    {
      perror ("pthread_create() error");
      exit (1);
    }

  if (pthread_join (thid, &ret) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }

  printf ("thread exited with '%s'\n", ret);
}

[root@centosgpt threaddemo]# ./create
thread() entered with argument 'thread 1'
thread exited with 'This is a test'.

//线程取消, 通过pthread_cancel 取消正在运行的线程
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int thstatus;

void *
thread (void *arg)
{
  puts ("thread has started. now sleeping");
  while (1)
    sleep (1);
}

main (int argc, char *argv[])
{
  pthread_t thid;
  void *status;

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create failed");
      exit (2);
    }

  if (pthread_cancel (thid) == -1)
    {
      perror ("pthread_cancel failed");
      exit (3);
    }

  if (pthread_join (thid, &status) == -1)
    {
      perror ("pthread_join failed");
      exit (4);
    }

  if (status == (int *) -1)
    puts ("thread was cancelled");
  else
    puts ("thread was not cancelled");

  exit (0);
}

[root@centosgpt threaddemo]# ./cancel
thread has started. now sleeping
thread was cancelled
// 线程分离, 线程退出后自动释放资源
#include <stdlib.h>
#include <stdio.h>

void *
thread (void *arg)
{
  char *ret;
  printf ("thread() entered with argument '%s'\n", arg);
  if ((ret = (char *) malloc (20)) == NULL)
    {
      perror ("malloc() error");
      exit (2);
    }
  strcpy (ret, "This is a test");
  pthread_exit (ret);
}

main ()
{
  pthread_t thid;
  void *ret;

  if (pthread_create (&thid, NULL, thread, "thread 1") != 0)
    {
      perror ("pthread_create() error");
      exit (1);
    }

  if (pthread_detach (&thid) != 0)
    {
      perror ("pthread_detach() error");
      exit (4);
    }

  sleep(2);
  printf ("thread exited with '%s'\n", ret);

}

[root@centosgpt threaddemo]# ./detach
thread() entered with argument 'thread 1'
thread exited with '(null)'
[root@centosgpt threaddemo]# ./detach
pthread_detach() error: Success
#include <pthread.h>
#include <stdio.h>

pthread_t thid, IPT;

void *
thread (void *arg)
{
  if (pthread_equal (IPT, thid))
    puts ("the thread is the IPT...?");
  else
    puts ("the thread is not the IPT");
}

main ()
{

  IPT = pthread_self ();

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (1);
    }

  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }
}


[root@centosgpt threaddemo]# ./self
the thread is not the IPT
[root@centosgpt threaddemo]#

私有数据

私有数据创建
pthread_key_create
pthread_key_delete 
私有数据使用   pthread_setspecific 
  pthread_getspecific 

私有数据 example

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>

#define threads 3
#define BUFFSZ  48
pthread_key_t key;

void *
threadfunc (void *parm)
{
  int status;
  void *value;
  int threadnum;
  int *tnum;
  void *getvalue;
  char Buffer[BUFFSZ];

  tnum = parm;
  threadnum = *tnum;

  printf ("Thread %d executing\n", threadnum);

  if (!(value = malloc (sizeof (Buffer))))
    printf ("Thread %d could not allocate storage, errno = %d\n",
            threadnum, errno);

  sprintf (value, "Thread %d executing\n", threadnum);
  status = pthread_setspecific (key, (void *) value);
  if (status < 0)
    {
      printf ("pthread_setspecific failed, thread %d, errno %d",
              threadnum, errno);
      pthread_exit ((void *) 12);
    }
  printf ("Thread %d setspecific value: %d\n", threadnum, value);

  getvalue = 0;
  getvalue = pthread_getspecific (key);
  if (status < 0)
    {
      printf ("pthread_getspecific failed, thread %d, errno %d",
              threadnum, errno);
      pthread_exit ((void *) 13);
    }
    printf("key = %s\n", getvalue);

  if (getvalue != value)
    {
      printf ("getvalue not valid, getvalue=%d", (int) getvalue);
      pthread_exit ((void *) 68);
    }

  pthread_exit ((void *) 0);
}

void
destr_fn (void *parm)
{
  printf ("Destructor function invoked\n");
  free (parm);
}

main ()
{
  int getvalue;
  int status;
  int i;
  int threadparm[threads];
  pthread_t threadid[threads];
  int thread_stat[threads];


  if ((status = pthread_key_create (&key, destr_fn)) < 0)
    {
      printf ("pthread_key_create failed, errno=%d", errno);
      exit (1);
    }

  for (i = 0; i < threads; i++)
    {
      threadparm[i] = i + 1;
      status = pthread_create (&threadid[i],
                               NULL, threadfunc, (void *) &threadparm[i]);
      if (status < 0)
        {
          printf ("pthread_create failed, errno=%d", errno);
          exit (2);
        }
    }

  for (i = 0; i < threads; i++)
    {
      status = pthread_join (threadid[i], (void *) &thread_stat[i]);
      if (status < 0)
        {
          printf ("pthread_join failed, thread %d, errno=%d\n", i + 1, errno);
        }

      if (thread_stat[i] != 0)
        {
          printf ("bad thread status, thread %d, status=%d\n", i + 1,
                  thread_stat[i]);
        }
    }
  exit (0);
}

[root@centosgpt threaddemo]# ./key
Thread 1 executing
Thread 2 executing
Thread 1 setspecific value: -1140848448
key = Thread 1 executing

Thread 2 setspecific value: -1275066176
key = Thread 2 executing

Thread 3 executing
Thread 3 setspecific value: -1207957312
key = Thread 3 executing

Destructor function invoked
Destructor function invoked
Destructor function invoked

同步:

互斥量

互斥量创建与销毁 pthread_mutex_init
pthread_mutex_destroy 
加锁解锁互斥量(阻塞) pthread_mutex_lock
pthread_mutex_unlock 
加锁解锁互斥量(非阻塞) pthread_mutex_trylock
互斥变量优先级上限 pthread_mutex_getprioceiling
pthread_mutex_setprioceiling 

互斥量 example

## 阻塞模式 pthread_mutex_lock

#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

pthread_mutex_t mutex;

void *
thread (void *arg)
{
  if (pthread_mutex_lock (&mutex) != 0)
    {
      perror ("pthread_mutex_lock() error");
      exit (1);
  }
  puts ("thread was granted the mutex");
  if (pthread_mutex_unlock(&mutex) != 0) {
      perror("pthread_mutex_unlock() error");
      exit(2);
  }
}

main ()
{
  pthread_t thid;

  if (pthread_mutex_init (&mutex, NULL) != 0)
    {
      perror ("pthread_mutex_init() error");
      exit (2);
    }

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }
  if (pthread_mutex_lock (&mutex) != 0){
        perror ("pthread_mutex_lock() error");
        exit (4);
  }
  puts ("IPT was granted the mutex");

  if (pthread_mutex_unlock(&mutex) != 0) {
      perror("pthread_mutex_unlock() error");
      exit(2);
  }
  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_mutex_trylock() error");
      exit (5);
    }

   if (pthread_mutex_destroy(&mutex) != 0) {
       perror("pthread_mutex_destroy() error");
           exit(2);
   }

}

[root@centosgpt threaddemo]# ./mutexb
IPT was granted the mutex
thread was granted the mutex
### 非阻塞模式
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
pthread_mutex_t mutex;

void *
thread (void *arg)
{
int rc;
  while (1){
      if ((rc=pthread_mutex_trylock (&mutex))!=0){
          if (rc == EBUSY){
             puts ("thread was denied access to the mutex");
             continue;
          }
          else {
             perror ("sub pthread_mutex_trylock() error");
             exit (1);
          }
          puts ("sub thread can do other thing");
      } else {
           puts ("thread was granted the mutex");
           break;
      }
  }
  if (pthread_mutex_unlock(&mutex) != 0) {
     perror("pthread_mutex_unlock() error");
     exit(2);
  }

}

main ()
{
  pthread_t thid;
  int rc;

  if (pthread_mutex_init (&mutex, NULL) != 0)
    {
      perror ("pthread_mutex_init() error");
      exit (2);
    }

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }
  while(1){
      if ((rc=pthread_mutex_trylock (&mutex)) != 0){
          if (rc == EBUSY){
              puts ("IPT was denied access to the mutex");
              continue;
          }
          else
          {
            perror ("main pthread_mutex_trylock() error");
            exit (4);
          }
          puts ("main thread can do other thing");
       }
       else {
          puts ("IPT was granted the mutex");
          break;
       }
  }

  if (pthread_mutex_unlock(&mutex) != 0) {
     perror("pthread_mutex_unlock() error");
     exit(2);
  }

  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_mutex_trylock() error");
      exit (5);
    }

   if (pthread_mutex_destroy(&mutex) != 0) {
       perror("pthread_mutex_destroy() error");
           exit(2);
   }

}

[root@centosgpt threaddemo]# ./mutex
IPT was granted the mutex
thread was denied access to the mutex
thread was granted the mutex

依赖于互斥锁属性的协议的设置

#include <pthread.h>
#include <stdio.h>

#define _POSIX_THREAD_PRIO_PROTECT

int
main (int argc, char **argv)
{
  pthread_mutex_t mutex;
  pthread_mutexattr_t attr;
  int prioceiling;
  int oldprioceiling;
  int rc;

  printf ("Entering testcase\n");


  pthread_mutexattr_init(&attr);
  pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_PROTECT);

  pthread_mutex_init (&mutex, &attr);

  rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
  printf ("get now prioceiling = %d\n", prioceiling);

  prioceiling = 88;
  printf ("set prioceiling = %d ready ...\n", prioceiling);
  rc = pthread_mutex_setprioceiling(&mutex, prioceiling, &oldprioceiling);
  if (!rc){
      rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
      printf ("OK prioceiling = %d oldprioceiling = %d\n", prioceiling, oldprioceiling);
  }
  else {
      printf ("FAIL set prioceiling err = %d\n", rc);
  }

  prioceiling = 100;
  printf ("set prioceiling = %d ready ...\n", prioceiling);
  rc = pthread_mutex_setprioceiling(&mutex,prioceiling, &oldprioceiling);
  if (!rc){
      rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
      printf ("OK prioceiling = %d oldprioceiling = %d\n", prioceiling, oldprioceiling);
  }
  else{
     printf ("FAIL set prioceiling err = %d\n", rc);
  }

  pthread_mutex_destroy(&mutex);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./mutexprio
Entering testcase
get now prioceiling = 1
set prioceiling = 88 ready ...
OK prioceiling = 88 oldprioceiling = 1
set prioceiling = 100 ready ...
FAIL set prioceiling err = 22
Main completed

条件变量 

条件变量创建与销毁
pthread_cond_destroy 
pthread_cond_init 
等待条件变量
pthread_cond_timedwait 
pthread_cond_wait 
唤醒条件变量等待线程 pthread_cond_broadcast 
pthread_cond_signal 

条件变量 example

// signal
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

pthread_cond_t cond;
pthread_mutex_t mutex;

int footprint = 0;

void *
thread (void *arg)
{
  time_t T;

  if (pthread_mutex_lock (&mutex) != 0)
    {
      perror ("pthread_mutex_lock() error");
      exit (6);
    }
  time (&T);
  printf ("starting wait at %s", ctime (&T));
  footprint++;

  if (pthread_cond_wait (&cond, &mutex) != 0)
    {
      perror ("pthread_cond_timedwait() error");
      exit (7);
    }
  time (&T);
  printf ("wait over at %s ", ctime (&T));

}


main ()
{
  pthread_t thid;
  time_t T;
  struct timespec t;

  if (pthread_mutex_init (&mutex, NULL) != 0)
    {
      perror ("pthread_mutex_init() error");
      exit (1);
    }

  if (pthread_cond_init (&cond, NULL) != 0)
    {
      perror ("pthread_cond_init() error");
      exit (2);
    }

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }

  while (footprint == 0)
    sleep (1);

  puts ("IPT is about ready to release the thread first");
  sleep (2);

  if (pthread_cond_signal (&cond) != 0)
    {
      perror ("pthread_cond_signal() error");
      exit (4);
    }
  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_join() error");
      exit (5);
    }
}

[root@centosgpt threaddemo]# ./cond
starting wait at Wed Jun 19 05:41:58 2019
IPT is about ready to release the thread first
wait over at Wed Jun 19 05:42:01 2019
//broadcase
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

pthread_cond_t cond;
pthread_mutex_t mutex;

int footprint = 0;

void *
thread (void *arg)
{
  time_t T;

  if (pthread_mutex_lock (&mutex) != 0)
    {
      perror ("pthread_mutex_lock() error");
      exit (6);
    }
  time (&T);
  printf ("starting wait at %s", ctime (&T));
  footprint++;

  if (pthread_cond_wait (&cond, &mutex) != 0)
    {
      perror ("pthread_cond_timedwait() error");
      exit (7);
    }
  time (&T);
  printf ("wait over at %s ", ctime (&T));

}


main ()
{
  pthread_t thid;
  time_t T;
  struct timespec t;

  if (pthread_mutex_init (&mutex, NULL) != 0)
    {
      perror ("pthread_mutex_init() error");
      exit (1);
    }

  if (pthread_cond_init (&cond, NULL) != 0)
    {
      perror ("pthread_cond_init() error");
      exit (2);
    }

  if (pthread_create (&thid, NULL, thread, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }

  while (footprint == 0)
    sleep (1);

  puts ("IPT is about ready to release the thread first");
  sleep (2);

  if (pthread_cond_broadcast (&cond) != 0)
  {
    perror ("pthread_cond_broadcast() error");
    exit (2);
  }

  if (pthread_cond_destroy (&cond) != 0)
  {
    perror ("pthread_cond_destroy() error");
    exit (3);
  }

  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_join() error");
      exit (5);
    }
}

[root@centosgpt threaddemo]# ./condb
starting wait at Wed Jun 19 05:44:07 2019
IPT is about ready to release the thread first
wait over at Wed Jun 19 05:44:10 2019

线程使用的几种方式:

流水线:

每个线程在流水线上执行特定操作,将结果传递给下一个线程;

输入 ->线程 1->线程2 ->线程3->输出

工作组:

由一组线程并行独立处理

                   |___线程1___|

输入———|___线程2___|———输出

                   |___线程3___|

客户端服务器 :

服务端独立执行操作, 客户端等待或并行执行

输入1                                   输出1

输入2———服务器———输出2

输入3                                  输出3

线程高级编程:

一次性初始化

一次性初始化 pthread_once 

 

      一次性初始化 example

#include <stdio.h>
#include <errno.h>
#include <pthread.h>

#define threads 3

int once_counter = 0;
pthread_once_t once_control = PTHREAD_ONCE_INIT;

void
once_fn (void)
{
  puts ("in once_fn");
  once_counter++;
}

void *
threadfunc (void *parm)
{
  int status;
  int threadnum;
  int *tnum;

  tnum = parm;
  threadnum = *tnum;

  printf ("Thread %d executing\n", threadnum);

  status = pthread_once (&once_control, once_fn);
  if (status < 0)
    printf ("pthread_once failed, thread %d, errno=%d\n", threadnum, errno);

  pthread_exit ((void *) 0);
}

main ()
{
  int status;
  int i;
  int threadparm[threads];
  pthread_t threadid[threads];
  int thread_stat[threads];

  for (i = 0; i < threads; i++)
    {
      threadparm[i] = i + 1;
      status = pthread_create (&threadid[i],
                               NULL, threadfunc, (void *) &threadparm[i]);
      if (status < 0)
        {
          printf ("pthread_create failed, errno=%d", errno);
          exit (2);
        }
    }

  for (i = 0; i < threads; i++)
    {
      status = pthread_join (threadid[i], (void *) &thread_stat[i]);
      if (status < 0)
        printf ("pthread_join failed, thread %d, errno=%d\n", i + 1, errno);

      if (thread_stat[i] != 0)
        printf ("bad thread status, thread %d, status=%d\n", i + 1,
                thread_stat[i]);
    }

  if (once_counter != 1)
    printf ("once_fn did not get control once, counter=%d", once_counter);
  exit (0);
}

[root@centosgpt threaddemo]# ./once
Thread 3 executing
in once_fn
Thread 2 executing
Thread 1 executing

线程取消

取消状态
pthread_setcancelstate
取消类型 pthread_setcanceltype 
pthread_cleanup_pop
pthread_cleanup_push 

线程取消 example

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *
threadfunc (void *parm)
{
  int i = 0;
  printf ("Entered secondary thread\n");
  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
  while (1)
    {
      printf ("Secondary thread is looping\n");
      pthread_testcancel ();
      sleep (1);
      if (++i == 5)
        {
          printf ("Cancel state set to ENABLE\n");
          pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
        }
    }   /* infinite */
  return NULL;
}

int
main (int argc, char **argv)
{
  pthread_t thread;
  int rc = 0;

  printf ("Entering testcase\n");

  /* Create a thread using default attributes */
  printf ("Create thread using the NULL attributes\n");
  rc = pthread_create (&thread, NULL, threadfunc, NULL);

  /* sleep() is not a very robust way to wait for the thread */
  sleep (3);

  printf ("Cancel the thread\n");
  rc = pthread_cancel (thread);

  /* sleep() is not a very robust way to wait for the thread */
  sleep (3);
  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./cancelstate
Entering testcase
Create thread using the NULL attributes
Entered secondary thread
Secondary thread is looping
Secondary thread is looping
Secondary thread is looping
Cancel the thread
Secondary thread is looping
Secondary thread is looping
Cancel state set to ENABLE
Secondary thread is looping
Main completed
#include <pthread.h>
#include <stdio.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void
cleanupHandler (void *parm)
{
  int rc;
  printf ("Inside cleanup handler, unlock mutex\n");
  rc = pthread_mutex_unlock ((pthread_mutex_t *) parm);
}

void *
threadfunc (void *parm)
{
  int rc;
  int oldtype;

  printf ("Entered secondary thread, lock mutex\n");
  rc = pthread_mutex_lock (&mutex);

  pthread_cleanup_push (cleanupHandler, &mutex);
  /* We must assume there is a good reason for async. cancellability   */
  /* and also, we must assume that if we get interrupted, it is        */
  /* appropriate to unlock the mutex. More than likely it is not       */
  /* because we will have left some data structures in a strange state */
  /* if we are async. interrupted while holding the mutex              */
  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

  printf ("Secondary thread is now looping\n");
  while (1)
    {
      sleep (1);
    }
  printf ("Unexpectedly got out of loop!\n");
  pthread_cleanup_pop (0);
  return NULL;
}

int
main (int argc, char **argv)
{
  pthread_t thread;
  int rc = 0;
  void *status;

  printf ("Enter Testcase - %s\n", argv[0]);

  /* Create a thread using default attributes */
  printf ("Create thread using the NULL attributes\n");
  rc = pthread_create (&thread, NULL, threadfunc, NULL);

  /* sleep() is not a very robust way to wait for the thread */
  sleep (1);

  printf ("Cancel the thread\n");
  rc = pthread_cancel (thread);

  rc = pthread_join (thread, &status);
  if (status != PTHREAD_CANCELED)
    {
      printf ("Unexpected thread status\n");
      exit (1);
    }
  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./canceltype
Enter Testcase - ./canceltype
Create thread using the NULL attributes
Entered secondary thread, lock mutex
Secondary thread is now looping
Cancel the thread
Inside cleanup handler, unlock mutex
Main completed

互斥变量属性

互斥量初始化与销毁: pthread_mutexattr_init 
pthread_mutexattr_destroy 
互斥量初范围: pthread_mutexattr_getpshared
pthread_mutexattr_setpshared
互斥量类型: pthread_mutexattr_gettype
pthread_mutexattr_settype 
设置互斥锁属性的协议 pthread_mutexattr_setprotocol 
pthread_mutexattr_getprotocol 
设置互斥锁属性的优先级上限 pthread_mutexattr_getprioceiling
pthread_mutexattr_setprioceiling 

互斥变量属性 example

// 互斥锁范围
#include <pthread.h>
#include <stdio.h>

void
showPshared (pthread_mutexattr_t * mta)
{
  int rc;
  int pshared;

  printf ("Check pshared attribute\n");
  rc = pthread_mutexattr_getpshared (mta, &pshared);
  //checkResults ("pthread_mutexattr_getpshared()\n", rc);

  printf ("The pshared attributed is: ");
  switch (pshared)
    {
    case PTHREAD_PROCESS_PRIVATE:
      printf ("PTHREAD_PROCESS_PRIVATE\n");
      break;
    case PTHREAD_PROCESS_SHARED:
      printf ("PTHREAD_PROCESS_SHARED\n");
      break;
    default:
      printf ("! pshared Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_mutexattr_t mta;
  int pshared = 0;

  printf ("Entering testcase\n");

  printf ("Create a default mutex attribute\n");
  rc = pthread_mutexattr_init (&mta);
  //checkResults ("pthread_mutexattr_init()\n", rc);
  showPshared (&mta);

  printf ("Change pshared attribute\n");
  rc = pthread_mutexattr_setpshared (&mta, PTHREAD_PROCESS_SHARED);
  //checkResults ("pthread_mutexattr_setpshared()\n", rc);
  showPshared (&mta);

  printf ("Destroy mutex attribute\n");
  rc = pthread_mutexattr_destroy (&mta);
  //checkResults ("pthread_mutexattr_destroy()\n", rc);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./mutexattr
Entering testcase
Create a default mutex attribute
Check pshared attribute
The pshared attributed is: PTHREAD_PROCESS_PRIVATE
Change pshared attribute
Check pshared attribute
The pshared attributed is: PTHREAD_PROCESS_SHARED
Destroy mutex attribute
Main completed
//  互斥锁类型
#include <pthread.h>
#include <stdio.h>

void
showPtype (pthread_mutexattr_t * mta)
{
  int rc;
  int ptype;

  printf ("Check pshared attribute\n");
  rc = pthread_mutexattr_gettype (mta, &ptype);

  printf ("The ptype attributed is: ");
  switch (ptype )
    {
//  case PTHREAD_MUTEX_DEFAULT:
    case PTHREAD_MUTEX_NORMAL:
      printf ("PTHREAD_MUTEX_NORMAL\n");
      break;
    case PTHREAD_MUTEX_ERRORCHECK:
      printf ("PTHREAD_MUTEX_ERRORCHECK\n");
      break;
    case PTHREAD_MUTEX_RECURSIVE:
      printf ("PTHREAD_MUTEX_RECURSIVE\n");
      break;
    default:
      printf ("! pshared Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_mutexattr_t mta;
  int pshared = 0;

  printf ("Entering testcase\n");

  printf ("Create a default mutex attribute\n");
  rc = pthread_mutexattr_init (&mta);
  showPtype (&mta);

  printf ("Change ptype attribute\n");
  rc = pthread_mutexattr_settype (&mta, PTHREAD_MUTEX_NORMAL);
  showPtype (&mta);
  rc = pthread_mutexattr_settype (&mta, PTHREAD_MUTEX_ERRORCHECK);
  showPtype (&mta);
  rc = pthread_mutexattr_settype (&mta, PTHREAD_MUTEX_RECURSIVE);
  showPtype (&mta);
  rc = pthread_mutexattr_settype (&mta, PTHREAD_MUTEX_DEFAULT);
  showPtype (&mta);

  printf ("Destroy mutex attribute\n");
  rc = pthread_mutexattr_destroy (&mta);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./mutextype
Entering testcase
Create a default mutex attribute
Check pshared attribute
The ptype attributed is: PTHREAD_MUTEX_NORMAL
Change ptype attribute
Check pshared attribute
The ptype attributed is: PTHREAD_MUTEX_NORMAL
Check pshared attribute
The ptype attributed is: PTHREAD_MUTEX_ERRORCHECK
Check pshared attribute
The ptype attributed is: PTHREAD_MUTEX_RECURSIVE
Check pshared attribute
The ptype attributed is: PTHREAD_MUTEX_NORMAL
Destroy mutex attribute
Main completed
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

void
showPprotocol (pthread_mutexattr_t * mta)
{
  int rc;
  int protocol;

  printf ("Check protocol attribute\n");
  rc = pthread_mutexattr_getprotocol (mta, &protocol);

  printf ("The protocal attributed is: ");
  switch (protocol)
    {
    case PTHREAD_PRIO_NONE:
      printf ("PTHREAD_PRIO_NONE\n");
      break;
    case PTHREAD_PRIO_INHERIT:
      printf ("PTHREAD_PRIO_INHERIT\n");
      break;
    case PTHREAD_PRIO_PROTECT:
      printf ("PTHREAD_PRIO_PROTECT\n");
      break;
    default:
      printf ("! protocol Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_mutexattr_t mta;
  int pshared = 0;

  printf ("Entering testcase\n");

  printf ("Create a default mutex attribute\n");
  rc = pthread_mutexattr_init (&mta);
  showPprotocol (&mta);

  printf ("Change protocal attribute\n");
  rc = pthread_mutexattr_setprotocol (&mta, PTHREAD_PRIO_NONE);
  showPprotocol (&mta);

  printf ("Change protocal attribute\n");
  rc = pthread_mutexattr_setprotocol (&mta, PTHREAD_PRIO_INHERIT);
  showPprotocol (&mta);

  printf ("Change protocal attribute\n");
  rc = pthread_mutexattr_setprotocol (&mta, PTHREAD_PRIO_PROTECT);
  showPprotocol (&mta);

  printf ("Destroy mutex attribute\n");
  rc = pthread_mutexattr_destroy (&mta);
  //checkResults ("pthread_mutexattr_destroy()\n", rc);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./mutexattrpro
Entering testcase
Create a default mutex attribute
Check protocol attribute
The protocal attributed is: PTHREAD_PRIO_NONE
Change protocal attribute
Check protocol attribute
The protocal attributed is: PTHREAD_PRIO_NONE
Change protocal attribute
Check protocol attribute
The protocal attributed is: PTHREAD_PRIO_INHERIT
Change protocal attribute
Check protocol attribute
The protocal attributed is: PTHREAD_PRIO_PROTECT
Destroy mutex attribute
Main completed
#include <pthread.h>
#include <stdio.h>

#define _POSIX_THREAD_PRIO_PROTECT

int
main (int argc, char **argv)
{
  pthread_mutex_t mutex;
  pthread_mutexattr_t attr;
  int prioceiling;
  int oldprioceiling;
  int rc;

  printf ("Entering testcase\n");


  pthread_mutexattr_init(&attr);
  pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_PROTECT);

  prioceiling = 55;
  pthread_mutexattr_setprioceiling(&attr, prioceiling);
  prioceiling = 0;
  pthread_mutexattr_getprioceiling(&attr, &prioceiling);
  printf ("get now mutexattr prioceiling = %d\n", prioceiling);

  pthread_mutex_init (&mutex, &attr);


  rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
  printf ("get now prioceiling = %d\n", prioceiling);

  prioceiling = 88;
  printf ("set prioceiling = %d ready ...\n", prioceiling);
  rc = pthread_mutex_setprioceiling(&mutex, prioceiling, &oldprioceiling);
  if (!rc){
      rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
      printf ("OK prioceiling = %d oldprioceiling = %d\n", prioceiling, oldprioceiling);
  }
  else {
      printf ("FAIL set prioceiling err = %d\n", rc);
  }

  prioceiling = 100;
  printf ("set prioceiling = %d ready ...\n", prioceiling);
  rc = pthread_mutex_setprioceiling(&mutex,prioceiling, &oldprioceiling);
  if (!rc){
      rc = pthread_mutex_getprioceiling(&mutex,&prioceiling);
      printf ("OK prioceiling = %d oldprioceiling = %d\n", prioceiling, oldprioceiling);
  }
  else{
     printf ("FAIL set prioceiling err = %d\n", rc);
  }

  pthread_mutex_destroy(&mutex);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./mutexattrprio
Entering testcase
get now mutexattr prioceiling = 55
get now prioceiling = 55
set prioceiling = 88 ready ...
OK prioceiling = 88 oldprioceiling = 55
set prioceiling = 100 ready ...
FAIL set prioceiling err = 22
Main completed

条件变量属性

条件变量初始化与销毁 pthread_condattr_init 
pthread_condattr_destroy 
条件变量范围 pthread_condattr_setpshared
pthread_condattr_getpshared 
条件变量时钟 pthread_condattr_getclock
pthread_condattr_setclock 

条件变量属性 example

//  条件变量范围
#include <pthread.h>
#include <stdio.h>

void
showPshared (pthread_condattr_t * cta)
{
  int rc;
  int pshared;

  printf ("Check pshared attribute\n");
  rc = pthread_condattr_getpshared (cta, &pshared);

  printf ("The pshared attributed is: ");
  switch (pshared)
    {
    case PTHREAD_PROCESS_PRIVATE:
      printf ("PTHREAD_PROCESS_PRIVATE\n");
      break;
    case PTHREAD_PROCESS_SHARED:
      printf ("PTHREAD_PROCESS_SHARED\n");
      break;
    default:
      printf ("! pshared Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_condattr_t cta;
  int pshared = 0;

  printf ("Entering testcase\n");

  printf ("Create a default condition attribute\n");
  rc = pthread_condattr_init (&cta);
  showPshared (&cta);

  printf ("Change pshared attribute\n");
  rc = pthread_condattr_setpshared (&cta, PTHREAD_PROCESS_SHARED);
  showPshared (&cta);

  printf ("Destroy condition attribute\n");
  rc = pthread_condattr_destroy (&cta);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./condattr
Entering testcase
Create a default condition attribute
Check pshared attribute
The pshared attributed is: PTHREAD_PROCESS_PRIVATE
Change pshared attribute
Check pshared attribute
The pshared attributed is: PTHREAD_PROCESS_SHARED
Destroy condition attribute
Main completed
// clock
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

void
showPclockid (pthread_condattr_t * mta)
{
  int rc;
  int pclockid;

  printf ("Check pclockid attribute\n");
  rc = pthread_condattr_getclock (mta, &pclockid);

  printf ("The pclockid attributed is: ");
  switch (pclockid)
    {
    case CLOCK_REALTIME:
      printf ("CLOCK_REALTIME\n");
      break;
    case CLOCK_MONOTONIC:
      printf ("CLOCK_MONOTONIC\n");
      break;
    default:
      printf ("! pclock Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_condattr_t cta;
  clockid_t clock_id;

  printf ("Entering testcase\n");

  printf ("Create a default condition attribute\n");
  rc = pthread_condattr_init (&cta);
  showPclockid (&cta);

  printf ("Change pclock attribute\n");
  rc = pthread_condattr_setclock (&cta, CLOCK_MONOTONIC);
  showPclockid (&cta);

  printf ("Destroy condition attribute\n");
  rc = pthread_condattr_destroy (&cta);

  printf ("Main completed\n");
  return 0;
}


[root@centosgpt threaddemo]# ./condclk
Entering testcase
Create a default condition attribute
Check pclockid attribute
The pclockid attributed is: CLOCK_REALTIME
Change pclock attribute
Check pclockid attribute
The pclockid attributed is: CLOCK_MONOTONIC
Destroy condition attribute
Main completed

线程属性

 线程初始化与销毁 pthread_attr_init 
pthread_attr_destroy 
 线程设置分离状态 pthread_attr_getdetachstate 
pthread_attr_setdetachstate 
线程设置栈大小
pthread_attr_getstacksize 
pthread_attr_setstacksize
线程设置栈地址   pthread_attr_setstackaddr 
pthread_attr_getstackaddr 
线程设置栈地址和大小  pthread_attr_getstack
pthread_attr_setstack 
线程设置栈溢出保护区大小
pthread_attr_getguardsize
pthread_attr_setguardsize
设置范围  pthread_attr_getscope 
pthread_attr_setscope 
设置调度策略 pthread_attr_getschedpolicy 
pthread_attr_setschedpolicy 
设置继承调度策略
pthread_attr_setinheritsched 
pthread_attr_getinheritsched 
 设置调度参数
pthread_attr_getschedparam 
pthread_attr_setschedparam 
 设置线程优先级 pthread_setschedparam
pthread_getschedparam
设置并行级别 pthread_setconcurrency 
pthread_getconcurrency 

线程属性 example

#include <pthread.h>
#include <stdio.h>

void
showPdetachstate (pthread_attr_t * pta)
{
  int rc;
  int state;

  printf ("Check thread attribute\n");
  rc = pthread_attr_getdetachstate (pta, &state);
  printf ("The thread attributes object indicates: ");
  switch (state)
    {
    case PTHREAD_CREATE_DETACHED:
      printf ("DETACHED\n");
      break;
    case PTHREAD_CREATE_JOINABLE:
      printf ("JOINABLE\n");
      break;
    default:
      printf ("! detachstate Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  pthread_t thread;
  int rc = 0;
  pthread_attr_t pta;
  int state;

  printf ("Enter Testcase - %s\n", argv[0]);

  printf ("Create a thread attributes object\n");
  rc = pthread_attr_init (&pta);

  rc = pthread_attr_setdetachstate (&pta, PTHREAD_CREATE_JOINABLE);
  showPdetachstate (&pta);

  rc = pthread_attr_setdetachstate (&pta, PTHREAD_CREATE_DETACHED);
  showPdetachstate (&pta);

  printf ("Destroy thread attributes object\n");
  rc = pthread_attr_destroy (&pta);

  printf ("Main completed\n");
  return 0;
}


[root@centosgpt threaddemo]# ./attrdetach
Enter Testcase - ./attrdetach
Create a thread attributes object
Check thread attribute
The thread attributes object indicates: JOINABLE
Check thread attribute
The thread attributes object indicates: DETACHED
Destroy thread attributes object
Main completed
  •  
#include <pthread.h>
#include <stdio.h>
#include <sched.h>


int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_attr_t pta;

  printf ("Enter Testcase - %s\n", argv[0]);

  printf ("Create a thread attributes object\n");
  rc = pthread_attr_init (&pta);

  size_t stacksize;
  rc = pthread_attr_getstacksize(&pta,&stacksize);
  printf ("get stacksize %ld \n", stacksize);

  stacksize = 10*stacksize;
  printf ("set stacksize = %ld ready...\n", stacksize);
  rc = pthread_attr_setstacksize(&pta,stacksize);
  if (!rc) {
      rc = pthread_attr_getstacksize(&pta,&stacksize);
      printf ("get stacksize %ld  OK \n", stacksize);
  }else{
      printf ("set stacksize FAIL %d \n", rc);
  }

  printf ("Destroy thread attributes object\n");
  rc = pthread_attr_destroy (&pta);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./attrstacksize
Enter Testcase - ./attrstacksize
Create a thread attributes object
get stacksize 8388608
set stacksize = 83886080 ready...
get stacksize 83886080  OK
Destroy thread attributes object
Main completed
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>

int  main (void)
{
  pthread_attr_t attr;
  int rc;
  void *stackaddr;
  void *mystack;

  if (pthread_attr_init (&attr) == -1)
    {
      perror ("error in pthread_attr_init");
      exit (1);
    }

  /* Get a big enough stack and align it on 4K boundary. */
  mystack = malloc (PTHREAD_STACK_MIN * 2);
  if (mystack != NULL)
    {
      printf ("Using PTHREAD_STACK_MIN to align stackaddr %08x.\n", mystack);
      mystack = (void *) ((((long) mystack + (PTHREAD_STACK_MIN - 1)) /
                           PTHREAD_STACK_MIN) * PTHREAD_STACK_MIN);
      printf ("after align stackaddr %08x.\n", mystack);
    }
  else
    {
      perror ("Unable to acquire storage.");
      exit (2);
    }

  printf ("Setting stackaddr to %08x\n",  mystack);
  rc = pthread_attr_setstackaddr (&attr, mystack);
  if (rc != 0)
    {
      printf ("pthread_attr_setstackaddr returned: %d\n", rc);
      exit (3);
    }
  else
    {
      printf ("Set stackaddr to %08x\n",mystack);
    }

  rc = pthread_attr_getstackaddr (&attr, &stackaddr);
  if (rc != 0)
    {
      printf ("pthread_attr_getstackaddr returned: %d\n", rc);
      exit (4);
    }
  else
    {
      printf ("Retrieved stackaddr is %08x\n", stackaddr);
    }

  rc = pthread_attr_destroy (&attr);
  if (rc != 0)
    {
      perror ("error in pthread_attr_destroy");
      printf ("Returned: %d, Error: %d\n", rc, errno);
      exit (5);
    }

  exit (0);
}

[root@centosgpt threaddemo]# ./attrstackaddr
Using PTHREAD_STACK_MIN to align stackaddr 01738010.
after align stackaddr 0173c000.
Setting stackaddr to 0173c000
Set stackaddr to 0173c000
Retrieved stackaddr is 0173c000
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>

int
main (void)
{
  pthread_attr_t attr;
  int rc;

  void *mystack;
  size_t mystacksize = 2 * PTHREAD_STACK_MIN;

  if (pthread_attr_init (&attr) == -1)
    {
      perror ("error in pthread_attr_init");
      exit (1);
    }

  /* Get a big enough stack and align it on 4K boundary. */
  mystack = malloc (PTHREAD_STACK_MIN * 3);
  if (mystack != NULL)
    {
      printf ("Using PTHREAD_STACK_MIN to align stackaddr %x.\n", mystack);
      mystack = (void *) ((((long) mystack + (PTHREAD_STACK_MIN - 1)) /
                           PTHREAD_STACK_MIN) * PTHREAD_STACK_MIN);
    }
  else
    {
      perror ("Unable to acquire storage.");
      exit (2);
    }

  printf ("Setting stackaddr to %x\n", mystack);
  printf ("Setting stacksize to %x\n", mystacksize);
  rc = pthread_attr_setstack (&attr, mystack, mystacksize);
  if (rc != 0)
    {
      printf ("pthread_attr_setstack returned: %d\n", rc);
      exit (3);
    }
  else
    {
      printf ("Set stackaddr to %x\n", mystack);
      printf ("Set stacksize to %x\n", mystacksize);
    }

  rc = pthread_attr_destroy (&attr);
  if (rc != 0)
    {
      perror ("error in pthread_attr_destroy");
      printf ("Returned: %d, Error: %d\n", rc, errno);
      exit (4);
    }

  exit (0);
}

[root@centosgpt threaddemo]# ./attrstack
Using PTHREAD_STACK_MIN to align stackaddr e80010.
Setting stackaddr to e84000
Setting stacksize to 8000
Set stackaddr to e84000
Set stacksize to 8000
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>


#define PAGESIZE  getpagesize()
int
main (void)
{
  pthread_attr_t attr;
  int rc;
  size_t guardsize;

  if (pthread_attr_init (&attr) == -1)
    {
      perror ("error in pthread_attr_init");
      exit (1);
    }

  printf ("Set guardsize to value of PAGESIZE.\n");
  rc = pthread_attr_setguardsize (&attr, PAGESIZE);
  if (rc != 0)
    {
      printf ("pthread_attr_setguardsize returned: %d\n", rc);
      exit (2);
    }
  else
    {
      printf ("Set guardsize is %d\n", PAGESIZE);
    }

  rc = pthread_attr_getguardsize (&attr, &guardsize);
  if (rc != 0)
    {
      printf ("pthread_attr_getguardsize returned: %d\n", rc);
      exit (3);
    }
  else
    {
      printf ("Retrieved guardsize is %d\n", guardsize);
    }

  rc = pthread_attr_destroy (&attr);
  if (rc != 0)
    {
      perror ("error in pthread_attr_destroy");
      exit (4);
    }

  exit (0);
}

//scope specified the value PTHREAD_SCOPE_PROCESS, which is not supported on Linux.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

void
showPscope (pthread_attr_t * pta)
{
  int scope;

  printf ("Check scope attribute\n");
  pthread_attr_getscope (pta, &scope);

  printf ("The scope attributed is: ");
  switch (scope )
    {
    case PTHREAD_SCOPE_SYSTEM:
      printf ("PTHREAD_SCOPE_SYSTEM\n");
      break;
    case PTHREAD_SCOPE_PROCESS:
      printf ("PTHREAD_SCOPE_PROCESS\n");
      break;
    default:
      printf ("! scope Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_attr_t pta;
  int pshared = 0;

  printf ("Entering testcase\n");

  printf ("Create a defaultattribute\n");
  rc = pthread_attr_init (&pta);
  showPscope (&pta);

  //scope specified the value PTHREAD_SCOPE_PROCESS, which is not supported on Linux.
  printf ("Change scope attribute\n");
  rc = pthread_attr_setscope (&pta, PTHREAD_SCOPE_PROCESS);
  printf("rc = %d\n", rc);
  showPscope (&pta);

  printf ("Change scope attribute\n");
  rc = pthread_attr_setscope (&pta, PTHREAD_SCOPE_SYSTEM);
  showPscope (&pta);

  printf ("Destroy attribute\n");
  rc = pthread_attr_destroy (&pta);

  printf ("Main completed\n");
  return 0;
}


[root@centosgpt threaddemo]# ./attrscope
Entering testcase
Create a defaultattribute
Check scope attribute
The scope attributed is: PTHREAD_SCOPE_SYSTEM
Change scope attribute
rc = 95
Check scope attribute
The scope attributed is: PTHREAD_SCOPE_SYSTEM
Change scope attribute
Check scope attribute
The scope attributed is: PTHREAD_SCOPE_SYSTEM
Destroy attribute
Main completed
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

void
showPsched (pthread_attr_t * pta)
{
  int policy;

  printf ("Check sched attribute\n");
  pthread_attr_getschedpolicy (pta, &policy);

  printf ("The scope attributed is: ");
  switch (policy)
    {
    case SCHED_FIFO:
      printf ("SCHED_FIFO\n");
      break;
    case SCHED_RR:
      printf ("SCHED_RR\n");
      break;
    case SCHED_OTHER:
      printf ("SCHED_OTHER\n");
      break;
    default:
      printf ("! policy Error !\n");
      exit (1);
    }
  return;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_attr_t pta;
  int sched = 0;

  printf ("Entering testcase\n");

  printf ("Create a defaultattribute\n");
  rc = pthread_attr_init (&pta);
  showPsched (&pta);

  printf ("Change sched attribute\n");
  rc = pthread_attr_setschedpolicy (&pta, SCHED_FIFO);
  showPsched (&pta);

  printf ("Change sched attribute\n");
  rc = pthread_attr_setschedpolicy (&pta, SCHED_RR);
  showPsched (&pta);

  printf ("Change sched attribute\n");
  rc = pthread_attr_setschedpolicy (&pta, SCHED_OTHER);
  showPsched (&pta);

  printf ("Destroy attribute\n");
  rc = pthread_attr_destroy (&pta);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./attrsched
Entering testcase
Create a defaultattribute
Check sched attribute
The scope attributed is: SCHED_OTHER
Change sched attribute
Check sched attribute
The scope attributed is: SCHED_FIFO
Change sched attribute
Check sched attribute
The scope attributed is: SCHED_RR
Change sched attribute
Check sched attribute
The scope attributed is: SCHED_OTHER
Destroy attribute
Main completed

      当继承策略设置为PTHREAD_EXPLICIT_SCHED时 , 由于需要显示设置所有需要通过pthread_attr_setschedpolicy (&attr, SCHED_RR)设置 调度策略, 通过
pthread_attr_setschedparam (&attr, &param)设置优先级, 如果设置运行时会报错。本机实现是出现了Segement Fault错误。 

#include <pthread.h>
#include <stdio.h>

static void
display_sched_attr (int policy, struct sched_param *param)
{
  printf ("    policy=%s, priority=%d\n",
          (policy == SCHED_FIFO) ? "SCHED_FIFO" :
          (policy == SCHED_RR) ? "SCHED_RR" :
           (policy == SCHED_OTHER) ? "SCHED_OTHER" : "???", param->sched_priority);
}

static void display_thread_sched_attr (char *msg)
{
  int policy, s;
  struct sched_param param;

  s = pthread_getschedparam (pthread_self (), &policy, &param);

  printf ("%s\n", msg);
  display_sched_attr (policy, &param);
}

int
createsubthread (void *param)
{
  printf ("%s ",param);
  display_thread_sched_attr ("new thread");
  return NULL;
}


int
main (int argc, char **argv)
{
  pthread_t thread;
  int rc = 0;
  pthread_attr_t attr;
  char c;
  void *status;

  int policy, s;
  struct sched_param param;

  printf ("Enter Testcase - %s\n", argv[0]);

  policy = SCHED_FIFO;
  param.sched_priority = 2;
  pthread_setschedparam(pthread_self(), policy, &param);
  display_thread_sched_attr("main thread");

  rc = pthread_attr_init (&attr);
  rc = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);

  pthread_attr_setschedpolicy (&attr, SCHED_RR);
  pthread_attr_setschedparam (&attr, &param);

  //createthread show sched
  pthread_create (&thread, &attr, createsubthread, "PTHREAD_EXPLICIT_SCHED");
  pthread_join (thread, &status);

  sleep (2);

  rc = pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED);
  //createthread show sched
  pthread_create (&thread, &attr, createsubthread, "PTHREAD_INHERIT_SCHED");
  pthread_join (thread, &status);

  sleep (2);
  rc = pthread_attr_destroy (&attr);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./attrinherit
Enter Testcase - ./attrinherit
main thread
    policy=SCHED_FIFO, priority=2
PTHREAD_EXPLICIT_SCHED new thread
    policy=SCHED_RR, priority=2
PTHREAD_INHERIT_SCHED new thread
    policy=SCHED_FIFO, priority=2
Main completed

     并发度控制用户级线程可以映射内核线程或进程数, 由于Linux 线程模型是1:1 ,所有设置没有效果。

POSIX针对线程的调整

fork处理器 pthread_atfork 
stdio flockfile
ftrylockfile
funlockfile
getc_unlocked
getchar_unlocked
putc_unlocked
putchar_unlocked
线程安全 getlogin_r
ttyname_r
readdir_r
strtok_r
asctime_r
ctime_r
localtime_r
read_r
getgrgid_r
getgrnam_r
getpwuid_r
getpwnam_r
信号 pthread_sigmask 
pthread_kill 
sigwait
sigwaitinfo
sigtimedwait
sem_init
sem_destory
sem_wait
sem_trywait
sem_post
sem_getvalue

POSIX针对线程的调整 example

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

char fn_c[] = "childq.out";
char fn_p[] = "parentside.out";
int fd_c;
int fd_p;

void
prep1 (void)
{
  char buff[80] = "prep1\n";
  write (4, buff, sizeof (buff));
}

void
prep2 (void)
{
  char buff[80] = "prep2\n";
  write (4, buff, sizeof (buff));
}

void
prep3 (void)
{
  char buff[80] = "prep3\n";
  write (4, buff, sizeof (buff));
}


void
parent1 (void)
{
  char buff[80] = "parent1\n";
  write (4, buff, sizeof (buff));
}

void
parent2 (void)
{
  char buff[80] = "parent2\n";
  write (4, buff, sizeof (buff));
}

void
parent3 (void)
{
  char buff[80] = "parent3\n";
  write (4, buff, sizeof (buff));
}


void
child1 (void)
{
  char buff[80] = "child1\n";
  write (3, buff, sizeof (buff));
}

void
child2 (void)
{
  char buff[80] = "child2\n";
  write (3, buff, sizeof (buff));
}

void
child3 (void)
{
  char buff[80] = "child3\n";
  write (3, buff, sizeof (buff));
}

void *
thread1 (void *arg)
{

  printf ("Thread1: Hello from the thread.\n");

}


int
main (void)
{
  pthread_t thid;
  int rc, ret;
  pid_t pid;
  int status;
  char header[30] = "Called Child Handlers\n";


  if (pthread_create (&thid, NULL, thread1, NULL) != 0)
    {
      perror ("pthread_create() error");
      exit (3);
    }

  if (pthread_join (thid, NULL) != 0)
    {
      perror ("pthread_join() error");
      exit (5);
    }
  else
    {
      printf
        ("IPT: pthread_join success!  Thread 1 should be finished now.\n");
      printf ("IPT: Prepare to fork!!!\n");
    }

  /* Register call 1 */
  rc = pthread_atfork (&prep1, &parent2, &child3);
  if (rc != 0)
    {
      perror ("IPT: pthread_atfork() error [Call #1]");
    }


  /* Register call 2 */
  rc = pthread_atfork (&prep2, &parent3, &child1);
  if (rc != 0)
    {
      perror ("IPT: pthread_atfork() error [Call #2]");
    }


  /* Register call 3 */
  rc = pthread_atfork (&prep3, &parent1, NULL);
  if (rc != 0)
    {
      perror ("IPT: pthread_atfork() error [Call #3]");
    }

  /* Create output files to expose the execution of fork handlers. */
  if ((fd_c = creat (fn_c, S_IWUSR)) < 0)
    perror ("creat() error");
  else
    printf ("Created %s and assigned fd= %d\n", fn_c, fd_c);
  if ((ret = write (fd_c, header, 30)) == -1)
    perror ("write() error");
  else
    printf ("Write() wrote %d bytes in %s\n", ret, fn_c);

  if ((fd_p = creat (fn_p, S_IWUSR)) < 0)
    perror ("creat() error");
  else
    printf ("Created %s and assigned fd= %d\n", fn_p, fd_p);
  if ((ret = write (fd_p, header, 30)) == -1)
    perror ("write() error");
  else
    printf ("Write() wrote %d bytes in %s\n", ret, fn_p);

  pid = fork ();

  if (pid < 0)
    perror ("IPT: fork() error");
  else
    {
      if (pid == 0)
        {
          printf ("Child: I am the child!\n");
          printf ("Child: My PID= %d, parent= %d\n", (int) getpid (),
                  (int) getppid ());
          exit (0);

        }
      else
        {
          printf ("Parent: I am the parent!\n");
          printf ("Parent: My PID= %d, child PID= %d\n", (int) getpid (),
                  (int) pid);

          if (wait (&status) == -1)
            perror ("Parent: wait() error");
          else if (WIFEXITED (status))
            printf ("Child exited with status: %d\n", WEXITSTATUS (status));
          else
            printf ("Child did not exit successfully\n");

          close (fd_c);
          close (fd_p);

        }

    }
}

[root@centosgpt threaddemo]# ./atfork
Thread1: Hello from the thread.
IPT: pthread_join success!  Thread 1 should be finished now.
IPT: Prepare to fork!!!
Created childq.out and assigned fd= 3
Write() wrote 30 bytes in childq.out
Created parentside.out and assigned fd= 4
Write() wrote 30 bytes in parentside.out
Parent: I am the parent!
Parent: My PID= 62375, child PID= 62377
Child: I am the child!
Child: My PID= 62377, parent= 62375
Child exited with status: 0

[root@centosgpt threaddemo]# cat parentside.out
Called Child Handlers
prep3
prep2
prep1
parent2
parent3
parent1
[root@centosgpt threaddemo]# cat childq.out
Called Child Handlers
child3
child1

#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#define NUMTHREADS 3
void sighand (int signo);
static void
checkResults (char *string, int rc)
{
   if (rc)
   {
      printf ("Error on : %s, rc=%d", string, rc);
      exit (-1);
   }
   return;
}


void *
threadfunc (void *parm)
{
  pthread_t tid = pthread_self ();
  int rc;

  printf ("Thread 0x%.8x %.8x entered\n", tid);
  errno = 0;
  rc = sleep (30);
  if (rc != 0 && errno == EINTR)
    {
      printf ("Thread 0x%.8x %.8x got a signal delivered to it\n", tid);
      return NULL;
    }
  printf
    ("Thread 0x%.8x %.8x did not get expected results! rc=%d, errno=%d\n",
     tid, rc, errno);
  return NULL;
}

void *
threadmasked (void *parm)
{
  pthread_t tid = pthread_self ();
  sigset_t mask;
  int rc;

  printf ("Masked thread 0x%.8x %.8x entered\n", tid);

  sigfillset (&mask);           /* Mask all allowed signals */
  rc = pthread_sigmask (SIG_BLOCK, &mask, NULL);
  checkResults ("pthread_sigmask()\n", rc);

  errno = 0;
  rc = sleep (15);
  if (rc != 0)
    {
      printf ("Masked thread 0x%.8x %.8x did not get expected results! "
              "rc=%d, errno=%d\n", tid, rc, errno);
      return NULL;
    }
  printf ("Masked thread 0x%.8x %.8x completed masked work\n", tid);
  return NULL;
}

int
main (int argc, char **argv)
{
  int rc;
  int i;
  struct sigaction actions;
  pthread_t threads[NUMTHREADS];
  pthread_t maskedthreads[NUMTHREADS];

  printf ("Enter Testcase - %s\n", argv[0]);

  printf ("Set up the alarm handler for the process\n");
  memset (&actions, 0, sizeof (actions));
  sigemptyset (&actions.sa_mask);
  actions.sa_flags = 0;
  actions.sa_handler = sighand;

  rc = sigaction (SIGALRM, &actions, NULL);
  checkResults ("sigaction\n", rc);

  printf ("Create masked and unmasked threads\n");
  for (i = 0; i < NUMTHREADS; ++i)
    {
      rc = pthread_create (&threads[i], NULL, threadfunc, NULL);
      checkResults ("pthread_create()\n", rc);

      rc = pthread_create (&maskedthreads[i], NULL, threadmasked, NULL);
      checkResults ("pthread_create()\n", rc);
    }

  sleep (3);
  printf ("Send a signal to masked and unmasked threads\n");
  for (i = 0; i < NUMTHREADS; ++i)
    {
      rc = pthread_kill (threads[i], SIGALRM);
      checkResults ("pthread_kill()\n", rc);

      rc = pthread_kill (maskedthreads[i], SIGALRM);
      checkResults ("pthread_kill()\n", rc);
    }

  printf ("Wait for masked and unmasked threads to complete\n");
  for (i = 0; i < NUMTHREADS; ++i)
    {
      rc = pthread_join (threads[i], NULL);
      checkResults ("pthread_join()\n", rc);

      rc = pthread_join (maskedthreads[i], NULL);
      checkResults ("pthread_join()\n", rc);
    }
  printf ("Main completed\n");
  return 0;
}

void
sighand (int signo)
{
  pthread_t tid = pthread_self ();
  printf ("Thread 0x%.8x %.8x in signal handler\n", tid);
  return;
}

[root@centosgpt threaddemo]# ./sig
Enter Testcase - ./sig
Set up the alarm handler for the process
Create masked and unmasked threads
Thread 0xf7786700 63ff5491 entered
Masked thread 0xf6f85700 43ff5491 entered
Thread 0xf6784700 a3ff5491 entered
Masked thread 0xf5f83700 83ff5491 entered
Thread 0xf5782700 e3ff5491 entered
Masked thread 0xf4f81700 c3ff5491 entered
Send a signal to masked and unmasked threads
Wait for masked and unmasked threads to complete
Thread 0xf5782700 f5781740 in signal handler
Thread 0xf5782700 fffffffc got a signal delivered to it
Thread 0xf6784700 f6783740 in signal handler
Thread 0xf7786700 f7785740 in signal handler
Thread 0xf6784700 fffffffc got a signal delivered to it
Thread 0xf7786700 fffffffc got a signal delivered to it
Masked thread 0xf6f85700 00000000 completed masked work
Masked thread 0xf5f83700 00000000 completed masked work
Masked thread 0xf4f81700 00000000 completed masked work
Main completed

扩展同步

barrier 初始化与销毁 pthread_barrier_destroy
pthread_barrier_init
barrier 阻塞等待  pthread_barrier_wait
barrier 属性设置 pthread_barrierattr_destroy
pthread_barrierattr_getpshared
pthread_barrierattr_init
pthread_barrierattr_setpshared 
读写锁 初始化与销毁 pthread_rwlock_destroy 
pthread_rwlock_init 
读写锁 阻塞等待 pthread_rwlock_rdlock
pthread_rwlock_timedrdlock
pthread_rwlock_timedwrlock
pthread_rwlock_tryrdlock
pthread_rwlock_trywrlock
pthread_rwlock_unlock
pthread_rwlock_wrlock 
读写锁 属性设置 pthread_rwlockattr_destroy
pthread_rwlockattr_getpshared
pthread_rwlockattr_init
pthread_rwlockattr_setpshared 

扩展同步 example

barrier

 

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

int size;                       /* size equals the number of threads */
int *data;                      /* shared data, as many ints as size */
pthread_barrier_t our_barrier;  /* to synchronize */

void *
fun (void *args)
{
  int *id = (int *) args;
  int r = 1 + (rand () % 6);
  int k;
  char strd[size + 1];

  sleep (r);
  printf ("Thread %d has slept %d seconds ...\n", *id, r);
  data[*id] = r;

  pthread_barrier_wait (&our_barrier);

  for (k = 0; k < size; k++)
    strd[k] = '0' + ((char) data[k]);
  strd[size] = '\0';

  printf ("Thread %d has data : %s\n", *id, strd);
}

int
main (int argc, char *argv[])
{
  printf ("Give the number of threads : ");
  scanf ("%d", &size);
  data = (int *) calloc (size, sizeof (int));
  {
    pthread_t t[size];
    pthread_attr_t a;
    int id[size], i;

    pthread_barrier_init (&our_barrier, NULL, size);

    for (i = 0; i < size; i++)
      {
        id[i] = i;
        pthread_attr_init (&a);
        if (pthread_create (&t[i], &a, fun, (void *) &id[i]) != 0)
          printf ("Unable to create thread %d!\n", i);
      }
    printf ("Created %d threads ...\n", size);
    for (i = 0; i < size; i++)
      pthread_join (t[i], NULL);

    pthread_barrier_destroy (&our_barrier);
  }
  return 0;
}

[root@centosgpt threaddemo]# ./barrier
Give the number of threads : 2
Created 2 threads ...
Thread 0 has slept 2 seconds ...
Thread 1 has slept 5 seconds ...
Thread 1 has data : 25
Thread 0 has data : 25

读写锁

#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>

/* Simple function to check the return code and exit the program
   if the function call failed
      */
static void
compResults (char *string, int rc)
{
  if (rc)
    {
      printf ("Error on : %s, rc=%d", string, rc);
      exit (-1);
    }
  return;
}

pthread_rwlock_t rwlock;

void *
rdlockThread (void *arg)
{
  int rc;

  printf ("Entered thread, getting read lock\n");
  rc = pthread_rwlock_rdlock (&rwlock);
  compResults ("pthread_rwlock_rdlock()\n", rc);
  printf ("got the rwlock read lock\n");

  sleep (5);

  printf ("unlock the read lock\n");
  rc = pthread_rwlock_unlock (&rwlock);
  compResults ("pthread_rwlock_unlock()\n", rc);
  printf ("Secondary thread unlocked\n");
  return NULL;
}

void *
wrlockThread (void *arg)
{
  int rc;

  printf ("Entered thread, getting write lock\n");
  rc = pthread_rwlock_wrlock (&rwlock);
  compResults ("pthread_rwlock_wrlock()\n", rc);

  printf ("Got the rwlock write lock, now unlock\n");
  rc = pthread_rwlock_unlock (&rwlock);
  compResults ("pthread_rwlock_unlock()\n", rc);
  printf ("Secondary thread unlocked\n");
  return NULL;
}

int
main (int argc, char **argv)
{
  int rc = 0;
  pthread_t thread, thread1;

  printf ("Enter test case - %s\n", argv[0]);

  printf ("Main, initialize the read write lock\n");
  rc = pthread_rwlock_init (&rwlock, NULL);
  compResults ("pthread_rwlock_init()\n", rc);

  printf ("Main, grab a read lock\n");
  rc = pthread_rwlock_rdlock (&rwlock);
  compResults ("pthread_rwlock_rdlock()\n", rc);

  printf ("Main, grab the same read lock again\n");
  rc = pthread_rwlock_rdlock (&rwlock);
  compResults ("pthread_rwlock_rdlock() second\n", rc);

  printf ("Main, create the read lock thread\n");
  rc = pthread_create (&thread, NULL, rdlockThread, NULL);
  compResults ("pthread_create\n", rc);

  printf ("Main - unlock the first read lock\n");
  rc = pthread_rwlock_unlock (&rwlock);
  compResults ("pthread_rwlock_unlock()\n", rc);

  printf ("Main, create the write lock thread\n");
  rc = pthread_create (&thread1, NULL, wrlockThread, NULL);
  compResults ("pthread_create\n", rc);

  sleep (5);
  printf ("Main - unlock the second read lock\n");
  rc = pthread_rwlock_unlock (&rwlock);
  compResults ("pthread_rwlock_unlock()\n", rc);

  printf ("Main, wait for the threads\n");
  rc = pthread_join (thread, NULL);
  compResults ("pthread_join\n", rc);

  rc = pthread_join (thread1, NULL);
  compResults ("pthread_join\n", rc);

  rc = pthread_rwlock_destroy (&rwlock);
  compResults ("pthread_rwlock_destroy()\n", rc);

  printf ("Main completed\n");
  return 0;
}

[root@centosgpt threaddemo]# ./rwlock
Enter test case - ./rwlock
Main, initialize the read write lock
Main, grab a read lock
Main, grab the same read lock again
Main, create the read lock thread
Main - unlock the first read lock
Main, create the write lock thread
Entered thread, getting write lock
Entered thread, getting read lock
got the rwlock read lock
Main - unlock the second read lock
Main, wait for the threads
unlock the read lock
Secondary thread unlocked
Got the rwlock write lock, now unlock
Secondary thread unlocked
Main completed

          本篇笔记是极客时间 刘超《趣谈linux操作系统》 第11篇 课堂作业, 看了推荐的《ProgrammingwithPOSIXThreads中文     比较枯燥。 于是按照书中结构和oracle 多线程编程指南, 查找涉及相关API查找相关例子,跑了一遍。

           由于时间原因其中代码示例和排版都有不少问题, 后续还需完善。 整理成go by example 的形式

参考:

pthreads(7) - Linux manual page

Library functions

ORACLE多线程编程指南

Multithreaded Programming Guide

pthread_setschedparam

What does changing the concurrency level of a thread do?

http://man7.org/linux/man-pages/man3/pthread_setconcurrency.3.html

Using read-write locks

pthread_barrier_example

 

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注