1.线程标识
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_equal(pthread_t tid1,pthread_t tid2);
函数说明: 判断线程ID是否相等
返回值:若相等,返回非0数值,否则,返回0
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: pthread_t pthread_self(void);
函数说明:线程得到自己线程ID
返回值:调用线程的线程ID
*****************************************/
vi 11.1.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int main()
{
printf("进程ID: %d\n",getpid());
printf("线程ID: %ld\n",(long int)(pthread_self()));
return 0;
}
2.线程创建
/************************************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_create(pthread_t *restrict tidp,const pthread_attr_t * restrict attr,void *(*start_rtn)(void *),void * restrict arg);
函数说明:当pthread_create成功返回时,新创建线程的线程ID会被设置成tidp指向的内存单元,attr用于指定各种不同的线程属性
返回值:若成功,返回0,否则,返回错误编号
*********************************************************/
vi 11.2.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void* pthread_1(void *arg)
{
printf("pthread1 starting \n");
printf("线程1 ID: %ld\n",pthread_self());
printf("do we want to do\n");
printf("pthread1 ending\n");
return (void*)0;
}
void * pthread_2(void* arg)
{
printf("pthread2 starting \n");
printf("线程2 ID: %ld\n",pthread_self());
printf("do we want to do\n");
printf("pthread2 ending\n");
return (void*)0;
}
int main()
{
int err;
pthread_t tid1,tid2;
err = pthread_create(&tid1,NULL,pthread_1,NULL);
if (err != 0)
{
printf("pthread_create 1 error\n");
exit(0);
}
err = pthread_create(&tid2,pthread_2,NULL);
if (err != 0)
{
printf("pthread_create 2 error\n");
exit(0);
}
sleep(2);
return 0;
}
3.线程终止
vi 11.3.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* pthread_1(void* arg)
{
printf("线程 1 ID: %ld 进行中\n",pthread_self());
printf("do something you want to\n");
printf("exiting \n");
return (void*)1;
}
void * pthread_2(void *arg)
{
printf("线程 2 ID: %ld 进行中\n",pthread_self());
printf("do something you want to\n");
printf("exiting \n");
pthread_exit((void*)1);
}
int main()
{
int err;
pthread_t tid1,tid2;
void* rval_ptr;
err = pthread_create(&tid1,NULL);
if (err != 0)
{
printf("pthread_create 1 error\n");
exit(0);
}
if (pthread_join(tid1,&rval_ptr) != 0)
{
printf("pthread_join 1 error\n");
exit(0);
}
printf("thread 1 exit code is %ld\n",(long)rval_ptr);
err = pthread_create(&tid2,NULL);
if (err != 0)
{
printf("pthread_create 2 error\n");
exit(0);
}
if (pthread_join(tid2,&rval_ptr) != 0)
{
printf("pthread_join 2 error\n");
exit(0);
}
printf("thread 2 exit code is %ld\n",(long)rval_ptr);
return 0;
}
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_cancel(pthread_t tid);
函数说明:请求取消同一进程中的其他线程
返回值:若成功,返回0,否则,返回错误编号
*****************************************/
/**************************************************
包含头文件: #include <pthread.h>
函数原型: void pthread_cleanup_push(void(*rtn)(void*),void* arg);
void pthread_cleanup_pop(int execute);
函数说明: 压进或弹出线程退出函数
1.调用pthread_exit时
2.响应取消请求时
3.用非零execute参数调用pthread_cleanup_pop时
如果exec参数设置为0,清理函数将不被调用
发生1,2,3情况,pthread_cleanup_pop都会自动调用一次
*****************************************************/
vi 11.4.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t temp1,temp2;
void cleanup(void * arg)
{
printf("调用线程ID为: %ld existing \n",*(long*)arg);
}
void* pthread_1(void* arg)
{
printf("线程 1 ID %ld\n",pthread_self());
temp1 = pthread_self();
pthread_cleanup_push(cleanup,(void*)&temp1);
pthread_exit((void*)1);
pthread_cleanup_pop(0);
}
void* pthread_2(void *arg)
{
printf("线程 2 ID %ld\n",pthread_self());
temp2 = pthread_self();
pthread_cleanup_push(cleanup,(void*)&temp2);
pthread_exit((void*)2);
pthread_cleanup_pop(0);
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_create(&tid1,NULL);
if (err != 0)
{
printf("thread 1 create error\n");
exit(0);
}
err = pthread_create(&tid2,NULL);
if (err != 0)
{
printf("thread 2 create error\n");
exit(0);
}
err = pthread_join(tid1,NULL);
if (err != 0)
{
printf("pthread_join 1 error\n");
exit(0);
}
err = pthread_join(tid2,NULL);
if (err != 0)
{
printf("pthread_join 2 error\n");
exit(0);
}
return 0;
}
/***********************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_detach(pthread_t tid);
函数说明:进行线程分离,线程底层资源会被立即回收
,分离后不能用pthread_join等待它的终止状态
返回值:若成功,返回0,返回错误编号
************************************************/
4.线程同步
1.互斥量
/*********************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t * restrict atrr);
函数说明:初始化 pthread_mutex_t
可以通过常量 PTHREAD_MUTEX_INITIALIZER初始化(只适合用于静态分配),也可以通过pthread_mutex_init进行初始化,动态分配pthread_mutex_t时要调用pthread_mutex_destroy释放内存,attr初始化pthread_mutex_t属性
int pthread_mutex_destroy(pthread_mutex_t * mutex);
返回值:若成功,返回0,若出错,返回错误编号
*********************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型:1.int pthread_mutex_lock(pthread_mutex_t * mutex);
2. int pthread_mutex_trylock(pthread_mutex_t * mutex);
3.int pthread_mutex_unlock(pthread_mutex_t *mutex);
函数说明:1.若互斥量是锁住的,则该线程阻塞,直到互斥量被解锁,否则,锁住互斥量
2.若互斥量是锁住的,则调用失败,返回EBUSY,锁住互斥量
3.解锁互斥量
返回值:若成功,返回0,若失败,返回错误编号
*****************************************/
vi 11.5.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string>
#include <unistd.h>
//维护struct Student* next
pthread_mutex_t mutex_next = PTHREAD_MUTEX_INITIALIZER;
struct Student
{
int age;
std::string name;
char sex;
pthread_mutex_t mutex_mem;
struct Student* next = NULL;
};
struct Student* head = NULL;
void addRecord(struct Student s)
{
pthread_mutex_lock(&mutex_next);
if (head == NULL)
{
head = (struct Student*)malloc(sizeof(struct Student));
head->mutex_mem = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&head->mutex_mem);
head->age = s.age;
head->name = s.name;
head->sex = s.sex;
pthread_mutex_unlock(&head->mutex_mem);
pthread_mutex_unlock(&mutex_next);
return;
}
struct Student * temp = head;
while (temp->next != NULL)
temp = temp->next;
temp->next = (struct Student*)malloc(sizeof(struct Student));
pthread_mutex_init(&temp->next->mutex_mem,NULL);
pthread_mutex_lock(&temp->next->mutex_mem);
temp->next->age = s.age;
temp->next->name = s.name;
temp->next->sex = s.sex;
pthread_mutex_unlock(&temp->next->mutex_mem);
pthread_mutex_unlock(&mutex_next);
}
void* pthread_n(void* arg)
{
if (arg == NULL)
return (void*)1;
addRecord(*(struct Student*)arg);
pthread_exit((void*)0);
}
void display()
{
if (head == NULL)
return;
struct Student* temp = head;
while (temp != NULL)
{
printf("姓名: %s 年龄: %d 性别: %c\n",temp->name.c_str(),temp->age,temp->sex);
temp = temp->next;
}
}
int main()
{
struct Student s[5]
{
{19,"marco",'m'},{20,"Tom",{15,"Mary",'w'},{14,"Coco",{17,"Sam",'m'}
};
pthread_t tid[5];
int err;
for (int i = 0; i < 5; ++i)
{
err = pthread_create(&tid[i],pthread_n,&s[i]);
if (err != 0)
{
printf("thread %d create failure\n",i);
continue;
}
}
sleep(3);
display();
return 0;
}
5。读写锁
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict
attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
函数说明:可用常量PTHREAD_RWLOCK_INITIALIZER初始化(初始化静态分配的互斥量),pthread_rwlock_init也可初始化,对于动态分配的pthread_rwlock_t需要调用pthread_rwlock_destroy释放内存
返回值:若成功,返回错误编号
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: 1.int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
2.int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
3.int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
函数说明:读模式锁定读写锁,写模式锁定读写锁线程将被阻塞,待读模式读写锁全解锁时,写模式读写锁才可被锁定,写模式读写锁被锁定时,读模式读写锁被阻塞
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock);
函数说明:若不能立即锁定读模式的读写锁或锁定写模式的读写锁,函数返回错误编号EBUSY,否则立即锁定
返回值:若成功,返回错误编号
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_rwlock_timerdlock(pthread_rwlock_t * rwlock,const struct timespec *restrict tsptr);
int pthread_rwlock_timewrlock(pthread_rwlock_t * rwlock,const struct timespec *restrict tsptr);
函数说明:tsptr表示绝对时间,若超过绝对时间,返回错误编号ETIMEOUT
返回值:若成功,返回错误编号
*****************************************/
6.条件变量
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
函数说明: 可由PTHREAD_COND_INITIALIZER初始化pthread_cond_t(初始化静态分配的pthread_cond_t)或者以pthread_cond_init初始化pthread_cond_t,释放条件变量的底层空间之前,可以用pthread_cond_destroy进行反初始化
返回值:若成功,返回0,若出错,返回错误编号
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
int pthread_cond_timewait(pthread_cond_t *restrict cond,pthread_mutex_t * restrict mutex,const struct timespec *restrict tsptr);
函数说明:传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数,函数自动把调用线程放入等待队列,返回时,对互斥量再次加锁,tsptr是绝对时间,绝对时间内未返回就返回错误码变量
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: 1.int pthread_cond_signal(pthread_cond_t
*cond);
2.int pthread_cond_broadcast(pthread_cond_t *cond);
函数说明:1.唤醒至少一个等待条件变量满足的线程
2.唤醒所有所有等待条件变量满足的线程
返回值:若成功,返回错误编号
*****************************************/
vi 11.6.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* pthread_1(void* arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread 1 something after thread 2\n");
printf("thread 1 exiting\n");
pthread_mutex_unlock(&mutex);
pthread_exit((void*)0);
}
void* pthread_2(void* arg)
{
pthread_mutex_lock(&mutex);
printf("thread 2 do something before thread 1\n");
//......
printf("thread 2 exiting\n");
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
pthread_exit((void*)0);
}
void* pthread_3(void* arg)
{
pthread_mutex_lock(&mutex);
printf("thread 3 do something\n");
printf("thread 3 exiting\n");
pthread_mutex_unlock(&mutex);
pthread_exit((void*)0);
}
int main()
{
pthread_t tid1,tid2,tid3;
int err;
err = pthread_create(&tid1,NULL);
if (err != 0)
{
printf("thread create error\n");
exit(0);
}
err = pthread_create(&tid2,NULL);
if (err != 0)
{
printf("thread 2 create error\n");
exit(0);
}
err = pthread_create(&tid3,pthread_3,NULL);
if (err != 0)
{
printf("thread 3 create error\n");
exit(0);
}
sleep(2);
return 0;
}
7.自旋锁
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_spin_init(pthread_spinlock_t *lock,int pshared);
int pthread_spin_destroy(pthread_spinclok_t *lock);
函数说明:初始化pthread_spinlock_t,pshared可设置为PTHREAD_PROCESS_SHARED为多进程共享自旋锁,如果设置为PTHREAD_PROCESS_PRIVATE,则只能同一进程的多线程共享
pthread_spin_destroy进行pthread_spinlock_t进行反初始化
返回值:若成功,返回0,若出错,返回错误编号
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
函数说明:进行加锁,试图加锁,解锁
返回值:若成功,返回错误编号
*****************************************/
vi 11.7.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_spinlock_t spin;
void* pthread_1(void *arg)
{
pthread_spin_lock(&spin);
printf("thread 1 is starting\n");
printf("do something you want to do\n");
printf("thread 1 is exiting\n");
pthread_spin_unlock(&spin);
pthread_exit((void*)0);
}
void* pthread_2(void* arg)
{
pthread_spin_lock(&spin);
printf("thread 2 is starting\n");
printf("do something you want to do\n");
printf("thread 2 is exiting\n");
pthread_spin_unlock(&spin);
pthread_exit((void*)0);
}
void* pthread_3(void* arg)
{
pthread_spin_lock(&spin);
printf("thread 3 is starting\n");
printf("do something you want to do\n");
printf("thread 3 is exiting\n");
pthread_spin_unlock(&spin);
pthread_exit((void*)0);
}
int main()
{
pthread_t tid1,tid3;
int err;
err = pthread_spin_init(&spin,PTHREAD_PROCESS_PRIVATE);
if (err != 0)
{
printf("pthread spinlock init error\n");
exit(0);
}
err = pthread_create(&tid1,NULL);
if (err != 0)
{
printf("thread 1 create error\n");
exit(0);
}
err = pthread_create(&tid2,NULL);
if (err != 0)
{
printf("thread 3 create error\n");
exit(0);
}
err = pthread_create(&tid3,NULL);
if (err != 0)
{
printf("thread 3 create error\n");
exit(0);
}
sleep(2);
return 0;
}
8.屏障
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_barrier_init(pthread_barrier_t *restrict barrier,const pthread_barrierattr_t *restrict attr,unsigned int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);
函数说明:初始化pthread_barrier_t,count为允许所有线程运行之前必须到达屏障的线程数目,使用attr参数
指定屏障对象的属性
pthread_barrier_destroy反初始化释放分配给pthread_barrier_t的资源
返回值:若成功,返回为错误编号
*****************************************/
/*****************************************
包含头文件: #include <pthread.h>
函数原型: int pthread_barrier_wait(pthread_barrier_t * barrier);
函数说明:使未满足屏障计数的线程处于休眠状态,直到最后一个满足屏障计数的线程开始,所有线程将被唤醒
对于任意线程,pthread_barrier_wait的返回值为PTHREAD_BARRIER_SERIAL_THREAD,剩下的线程看到的返回值是0
返回值:若成功,返回为PTHREAD_BARRIER_SERIAL_THREAD,若出错,返回值为错误编号
*****************************************/
vi 11.8.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_barrier_t barrier;
void* pthread_1(void *arg)
{
printf("thread 1 is starting\n");
printf("thread 1 do something you want to do\n");
printf("thread 1 exiting\n");
pthread_barrier_wait(&barrier);
pthread_exit((void*)0);
}
void* pthread_2(void *arg)
{
printf("thread 2 is starting\n");
printf("thread 2 do something you want to do\n");
printf("thread 2 exiting\n");
pthread_barrier_wait(&barrier);
pthread_exit((void*)0);
}
void* pthread_3(void *arg)
{
printf("thread 3 is starting\n");
printf("thread 3 do something you want to do\n");
printf("thread 3 exiting\n");
pthread_barrier_wait(&barrier);
pthread_exit((void*)0);
}
int main()
{
pthread_t tid1,tid3;
pthread_barrier_init(&barrier,4);
printf("等待3个线程完成\n");
int err;
err = pthread_create(&tid1,NULL);
if (err != 0)
{
printf("thread 3 create error\n");
exit(0);
}
pthread_barrier_wait(&barrier);
printf("3 个线程已全部结束,主线程准备结束(第四个线程)\n");
return 0;
}