多线程基础之六:Pthread Win32实现的非阻塞请求机制的Semaphore
来源:互联网 发布:淘宝决斗盘 编辑:程序博客网 时间:2024/05/19 07:26
前面看到Windows API直接提供的Semaphore并没有为其配备等待队列,从而无法实现非阻塞请求机制以实现操作加速,对于临界区耗时的情况下,显然是存在实现非阻塞请求机制的Semaphore的。Linux下的Pthread库实现了这样的增加版Semaphore,幸运地是有Pthread的Win32版本。
前面讲解到其实Semaphore的完整结构体内容应该如下
typedef struct{ atomic_t count; int sleepers; wait_queue_head_t wait;} semaphore;
在启用非阻塞机制下,可以在Semaphores耗光资源计数的情况下,进入主动休眠状态,而非空等,从而可以集中计算资源给当前正处在临界区的线程(进程),所以该机制在临界区操作耗时较长的情况下是很有用的。Pthread库封装的Semaphores实现了阻塞和非阻塞请求的两种机制
下面可以单独看看pthread.h提供的semaphore相关的接口内容
typedef struct sem_t_ * sem_t;#define PTW32_DLLPORT __declspec (dllexport)PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, int pshared, //进程间共享标识,pthread win32位实现进程间semaphore共享,故而改位始终为0 unsigned int value);//value为初始给semaphore配备的可用资源数PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); //非阻塞请求PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); //阻塞请求,空等模式PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, const struct timespec * abstime); //等待有限时间后返回PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);//为semaphore增加1资源数PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, int count);//为semaphore增加count资源数PTW32_DLLPORT int __cdecl sem_open (const char * name, int oflag, mode_t mode, unsigned int value);//采用semaphore的名字寻找同名的内核对象,在进程间共享semaphore才需要用到,故而pthread win32未实现PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);PTW32_DLLPORT int __cdecl sem_unlink (const char * name);PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, int * sval);
test_time_pthread32_wait.cpp—“阻塞请求(空等)”模式下测试代码
#include <iostream>#include <stdio.h>#include <pthread.h>#include <sched.h>#include <semaphore.h>#include <time.h>#include <stdlib.h>#include <Windows.h>#pragma comment(lib, "pthreadVC2.lib") //必须加上这句using namespace std;sem_t sem;const int g_Number = 50;const int killTimeStep = 100000000;void* Function_t(void* Param){ sem_wait(&sem); //空等 int i = killTimeStep; while(i--); pthread_t myid = pthread_self(); printf("线程ID=%d ", myid); //cout<<"线程ID="<<static_cast<int>(myid)<<"线程编号= "<<(int)Param<<endl; cout<<"线程编号= "<<(int)Param<<endl; sem_post(&sem); return NULL;}int main(){ clock_t start_time = clock(); int ret = sem_init(&sem, 0, 0); if (!ret ) cout<<"主线程创建信号量成功,但主线程并没有激活该信号量"<<endl; else { cout<<"主线程创建信号量失败"<<endl; exit(EXIT_FAILURE); } pthread_t pid[ g_Number] = {0}; for (int i=0; i<g_Number; i++) pthread_create(&pid[i], NULL, Function_t,(void*)i); printf("创建大规模子线程成功\n"); if (sem_post(&sem) != 0) { printf("主线程激活信号量失败\n"); exit(EXIT_FAILURE); } printf("主线程激活了信号量,其他子线程可以开始使用。\n"); for (int i=0; i<g_Number; i++) pthread_join(pid[i], NULL); sem_destroy(&sem); clock_t end_time = clock(); cout<<"Running time is:"<<static_cast<double>(end_time - start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl; return 0;}
运行结果
*******************************—–******************************************
test_time_pthread32_trywait.cpp —“非阻塞请求”模式下测试代码
#include <iostream>#include <stdio.h>#include <pthread.h>#include <sched.h>#include <semaphore.h>#include <time.h>#include <stdlib.h>#include <Windows.h>#pragma comment(lib, "pthreadVC2.lib") //必须加上这句using namespace std;sem_t sem;const int g_Number = 50;const int killTimeStep = 100000000;void* Function_t(void* Param){ sem_trywait(&sem); //非阻塞请求 int i = killTimeStep; while(i--); pthread_t myid = pthread_self(); printf("立即线程 ID=%d ", myid); fflush(stdout); printf("立即线程-编号=%d\n",(int)Param); //这里受限于printf()此类IO的延迟写策略,导致了存在输出错行的可能性 fflush(stdout); //cout<<"线程ID="<<static_cast<long int>(myid)<<"线程编号= "<<(int)Param<<endl; //cout<<"线程编号= "<<(int)Param<<endl; sem_post(&sem); return NULL;}int main(){ clock_t start_time = clock(); int ret = sem_init(&sem, 0, 0); //第二个参数代表进程间共享标示位,但是pthread win32并没有实现,所以一直为0; //第三个参数代表给信号量初始分配的资源数,不像WINAPI CreateSemaphores(xxx)需要指定资源上限,pthread采用了默认资源上限 if (!ret ) cout<<"主线程创建try信号量成功,但主线程并没有激活该信号量"<<endl; else { cout<<"主线程创建信号量失败"<<endl; exit(EXIT_FAILURE); } pthread_t pid[ g_Number] = {0}; for (int i=0; i<g_Number; i++) pthread_create(&pid[i], NULL, Function_t,(void*)i); printf("创建大规模子线程成功\n"); if (sem_post(&sem) != 0) { printf("主线程激活信号量失败\n"); exit(EXIT_FAILURE); } printf("主线程激活了信号量,其他子线程可以开始使用。\n"); for (int i=0; i<g_Number; i++) pthread_join(pid[i], NULL); sem_destroy(&sem); clock_t end_time = clock(); cout<<"Running time is:"<<static_cast<double>(end_time - start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl; return 0;}
运行结果
*******************************—–******************************************
Conclusion: 可以看到pthread Win32实现的semaphore提供的“非阻塞请求机制”比“阻塞请求”在临界区操作耗时的场景下可以显著加速程序运行,提高性能,这点在并行计算中要重点使用。
- 多线程基础之六:Pthread Win32实现的非阻塞请求机制的Semaphore
- 多线程之实现同步的信号量Semaphore
- 多线程下非阻塞堆栈的实现
- 说说多线程pthread的基础
- win32多线程非阻塞与阻塞
- semaphore的实现机制详解
- semaphore的实现机制详解
- semaphore的实现机制详解
- Linux下套接字详解(六)----基于pthread的多线程的TCP套接字(阻塞/同步/并发)
- iOS中多线程的实现方案之pthread和NSThread
- Java多线程之~~~线程安全容器的非阻塞容器
- 同步/异步与阻塞/非阻塞的区别--多线程编程基础
- 同步/异步与阻塞/非阻塞的区别--多线程编程基础
- 同步/异步与阻塞/非阻塞的区别--多线程编程基础
- 非阻塞connect的实现
- 非阻塞connect的实现
- 非阻塞connect的实现
- 非阻塞connect的实现
- 什么是观察者模式`?
- 黑马Javaweb网上书城项目笔记
- IDEA使用技巧总结
- 论一个python程序猿的个人修养(一)
- 基础语法C语言——第一个程序HelloWorld
- 多线程基础之六:Pthread Win32实现的非阻塞请求机制的Semaphore
- 易错3(pow)
- java获得项目绝对路径
- Swift-如何存储数据在本地
- vba基础打卡4
- maven 学习(二)
- ubuntu关机重启命令介绍
- C语言的二维数组、及多维数组的降维
- java8的日期API总结(JSR310)