C++线程池实战

首先说一下C++的多线程吧,主要就是pthread库的使用,pthread库并非Linux系统的默认库,我们在执行的时候一般要加上-lpthread的参数。先说下几个常见的重点函数。

第一个就是pthread_create,这个是创建线程(注意不是启动喔),ret = pthread_create(&tids[i], NULL, service_thread_func, (void *)&thread_datas[i]); 其中第一个参数是线程,第一个参数为指向线程标识符的指针;第二个参数用来设置线程属性;第三个参数是线程运行函数的地址;最后一个参数是运行函数的参数。

然后第二个就是pthread_join,这个是用来主线程等待另一个线程的结束。第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值(一般写NULL就行了)。


介绍一下信号量(Semaphore),注意它和互斥锁mutex的区别。最直观的一点就在于互斥锁保证了同一时刻只有一个线程在操作而信号量可能会有多个线程在使用。

sem_post是释放信号量的。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。

sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。

sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同 时对同一个文件进行读、加和写操作的两个程序就有可能会引起冲突。信号量的值永远会正确地加一个“2”--因为有两个线程试图改变它。

sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。信号量这种“只用一个函数就能原子化地测试和设置”的能力下正是它的价值所在。还有另外一个信号量函数sem_trywait,它是sem_wait的非阻塞搭档。

函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。在成功完成之后会返回零。其他任何返回值都表示出现了错误。  

函数sem_destroy(sem_t *sem)用来释放信号量sem,属于无名信号量。

有了信号量之后,我们可以很轻松地实现一个生产者-使用者模型:

Ref

Linux信号量 sem_t简介

代码链接

https://github.com/ZhaoYi1031/pthread-pool

另外,对于涉及到信号量的操作,不可以在MAC系统下执行,因为MAC OSX不允许创建匿名信号量,你在苹果终端下man sem_init或者sem_destroy,是什么都看不到的。苹果自己有一套semaphore的api。非常有毒。

点赞
  1. zy说道:

    Unnamed semaphores are not supported, you need to use named semaphores.

    To use named semaphores instead of unnamed semaphores, use sem_open instead of sem_init, and use sem_close and sem_unlink instead of sem_destroy.

    摘自https://stackoverflow.com/questions/1413785/sem-init-on-os-x

发表评论

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