函数说明:

线程

int pthread_create(pthread_t restrict tidp, const pthread_attr_t restrict attr, void (start_rtn)(void ), void restrict arg);
int pthread_exit(void rval_ptr);
int pthread_join(pthread_t thread, void *
rval_ptr);
pthread_t pthread_self(void);//获取线程ID

互斥锁

int pthread_mutex_init(pthread_mutex_t restrict mutex, const pthread_mutexattr_t restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_trylock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);

条件变量

int pthread_cond_init(pthread_cond_t restrict cond, const pthread_condattr_t restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
int pthread_cond_wait(pthread_cond_t restrict cond, pthread_mutex_t restrict mutex);
int pthread_cond_timedwait(pthread_cond_t restrict cond, pthread_mutex_t restrict mutex, cond struct timespec *restrict timeout);
int pthread_cond_broadcast(pthread_cond_t cond);
int pthread_cond_signal(pthread_cond_t cond);

信号量强调的是线程或者进程之间的同步,条件变量和互斥锁是对不同线程的代码访问同一段内存区域的控制。信号量只要不为零就可以down

条件变量和互斥锁的区别

  1. 互斥锁必须是谁上锁就由谁来解锁,而信号量的wait和post操作不必由同一个线程执行。
  2. 互斥锁要么被锁住,要么被解开,和二值信号量类似
  3. sem_post是各种同步技巧中,唯一一个能在信号处理程序中安全调用的函数
  4. 互斥锁是为上锁而优化的;条件变量是为等待而优化的; 信号量既可用于上锁,也可用于等待,因此会有更多的开销和更高的复杂性
  5. 互斥锁,条件变量都只用于同一个进程的各线程间,而信号量(有名信号量)可用于不同进程间的同步。当信号量用于进程间同步时,要求信号量建立在共享内存区。
  6. 信号量有计数值,每次信号量post操作都会被记录,而条件变量在发送信号时,如果没有线程在等待该条件变量,那么信号将丢失。

    对互斥锁mutex的介绍

    include
    int pthread_mutex_init(pthread_mutex_t *mutex, const phread_mutexattr_t mutexattr );
    //mutex指向要操作的目标锁,pthread_mutex_t是一个结构体
    //mutexattr指明互斥锁的属性,NULL表明使用默认属性,默认属性下是普通锁
    //当一个线程对普通锁加锁之后,其余请求该锁的线程将形成一个等待队列,并在该锁被解锁是按优先级获得它
    问题:一个线程对一个已经加锁的普通锁加锁,将引发死锁
    一个已经解锁的普通锁再次解锁,将导致不可预期的后果

  1. 条件变量:用在线程之间同步共享数据的值,条件变量提供了一种机制,当共享数据达到某个值的时候,
  2. 唤醒等待这个共享数据的线程
  3. pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* cond_attr);
  4. 第一个参数cond指向将要操作的目标条件变量,条件变量类型是pthread_cond_t结构体
  5. cond_attr指定条件变量的属性。如果设置为NULL表示使用默认时薪

*/

//创建互斥量cond:
//
//pthread_cond_t cond = PTHREAD_COND_INITIALIZER
//
//还可以通过函数的方式创建:
//
//int pthread_cond_init(pthread_cond_t * cond, NULL);
//
//注意:两种方式创建有所区别,第一种是创建静态全局的,所创建的量在全局区,
//第二种创建的量在栈,两种的区别我们可以理解为全局变量和局部变量的差异,
//如果创建的是全局的条件量则用第一种方式初始化,如果是在函数内部创建则用第二种方式。
//这里其实跟互斥锁一样,互斥锁也可以用这两种方式初始化,原理相同。

//int pthreadcond_destroy(pthread_cond_t* cond);
//
//注意:只有在没有线程使用该互斥量的时候才能销毁,否则会返回EBUSY。
//
//等待:
//
//当线程不满足给定条件时,让线程挂起,挂起分为两种,一种是无限制的等待,pthread_cond_wait;
//一种是定时等待,pthread_cond_timedwait。无论是哪种等待都必须和锁配合使用
//,防止多个线程同时使用互斥量。
//
//注意两个函数
//
//pthread_cond_wait(pthread_cond_t
cond, pthreadmutex_t mutex);
//
//pthreadcond_timedwait(pthread_cond_t cond, pthreadmutex_t mutex, const struct timespec time);
//
//
//唤醒:
//
//当线程满足某个条件时,可以唤醒被挂起的线程,唤醒有两个函数
//
//一是唤醒等待该互斥量的线程:
//
//pthread_cond_signal(pthread_cond_t
cond);
//
//二是唤醒所有等待线程:

//pthread_cond_broadcast(pthread_cond_t* cond);

//void pthread_exit(void* retval);
//通过retval参数想线程的回收者传递其退出信息,该函数执行完毕之后不会返回到调用者,而且永远不会失败。

线程

创建新线程的函数:

int pthreadcreate(pthread_t thread, const pthreadattr_t arr,
void ( _start_routine)(void), void_ arg);
thread参数是新线程的标识符
arr == NULL表示使用默认新线程属性
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。

C++11线程睡眠的方式

  1. std::this_thread::sleep_for(std::chrono::seconds(3)); //休眠三秒
  2. std::this_thread::sleep_for(std::chrono:: milliseconds (100)); //休眠100毫秒

一个线程池包括以下四个基本组成部分:

(1)、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;

(2)、工作线程(WorkThread):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;

(3)、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

(4)、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。