APUE第十一章学习笔记

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,NULL,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,pthread_1,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,pthread_2,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,pthread_1,NULL);
    if (err != 0)
    {
    printf("thread 1 create error\n");
    exit(0);
    }


    err = pthread_create(&tid2,NULL,pthread_2,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",'m'},
    {15,"Mary",'w'},
    {14,"Coco",'w'},
    {17,"Sam",'m'}
    };
    pthread_t tid[5];
    int err;

    for (int i = 0; i < 5; ++i)
    {
    err = pthread_create(&tid[i],NULL,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释放内存
返回值:若成功,返回0,若失败,返回错误编号
*****************************************/


/*****************************************
包含头文件:  #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,否则立即锁定
返回值:若成功,返回0,若失败,返回错误编号
*****************************************/


/*****************************************
包含头文件:  #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
返回值:若成功,返回0,若失败,返回错误编号
*****************************************/

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.唤醒所有所有等待条件变量满足的线程
返回值:若成功,返回0,若失败,返回错误编号
*****************************************/

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,pthread_1,NULL);
    if (err != 0)
    {
    printf("thread create error\n");
    exit(0);
    }

    err = pthread_create(&tid2,NULL,pthread_2,NULL);
    if (err != 0)
    {
    printf("thread 2 create error\n");
    exit(0);
    }

    err = pthread_create(&tid3,NULL,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);
函数说明:进行加锁,试图加锁,解锁
返回值:若成功,返回0,若出错,返回错误编号
*****************************************/

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,tid2,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,pthread_1,NULL);
    if (err != 0)
    {
    printf("thread 1 create error\n");
    exit(0);
    }

    err = pthread_create(&tid2,NULL,pthread_2,NULL);
    if (err != 0)
    {
    printf("thread 3 create error\n");
    exit(0);
    }

    err = pthread_create(&tid3,NULL,pthread_3,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的资源
返回值:若成功,返回0,若出错,返回为错误编号
*****************************************/











/*****************************************
包含头文件:  #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,tid2,tid3;

    pthread_barrier_init(&barrier,NULL,4);
    printf("等待3个线程完成\n");

    int err;

    err = pthread_create(&tid1,NULL,pthread_1,NULL);
    if (err != 0)
    {
    printf("thread 1 create error\n");
    exit(0);
    }

    err = pthread_create(&tid2,NULL,pthread_2,NULL);
    if (err != 0)
    {
    printf("thread 2 create error\n");
    exit(0);
    }

    err = pthread_create(&tid3,NULL,pthread_3,NULL);
    if (err != 0)
    {
    printf("thread 3 create error\n");
    exit(0);
    }

    pthread_barrier_wait(&barrier);

    printf("3 个线程已全部结束,主线程准备结束(第四个线程)\n");
    return 0;
}

这里写图片描述

发布了236 篇原创文章 · 获赞 182 · 访问量 18万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 我行我“速” 设计师: Amelia_0503

分享到微信朋友圈

×

扫一扫,手机浏览