定义:
并发与并行:
- 并发(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
互斥变量属性
互斥变量属性 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
线程属性
线程属性 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, ¶m)设置优先级, 如果设置运行时会报错。本机实现是出现了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, ¶m);
printf ("%s\n", msg);
display_sched_attr (policy, ¶m);
}
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, ¶m);
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, ¶m);
//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
- fork处理器
#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
扩展同步
扩展同步 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
Multithreaded Programming Guide
What does changing the concurrency level of a thread do?
http://man7.org/linux/man-pages/man3/pthread_setconcurrency.3.html
Be First to Comment