一、线程间同步的几种方式

从上篇博文中可以发现,当多个线程对同一资源进行使用时,会产生“争夺”的情况,为了避免这种情况的产生,也就出现了线程间的同步这个技术。线程间的同步有多种方式,在接下来的博文中我会依次介绍几种主流的同步方式,以及他们之间的区别。在本篇博文中将介绍使用信号量Semaphore达到线程间同步的目的。老规矩,所有代码都讲在win32平台和Linux平台下都实现一遍。

相关函数和头文件

//头文件
#include <windows.h> //创建信号量API
HANDLE WINAPI CreateSemaphore(
_In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,//指向SECURITY_ATTRIBUTES的指针;
_In_ LONG lInitialCount, //信号量对象的初始值;
_In_ LONG lMaximumCount, //信号量对象的最大值,这个值必须大于0;
_In_opt_ LPCTSTR lpName //信号量对象的名称;
); //等待信号量API
DWORD WINAPI WaitForSingleObject(
_In_ HANDLE hHandle, //信号量对象句柄
_In_ DWORD dwMilliseconds //等待信号量时间,INFINET代表永久等待;
);
返回值:
WAIT_ABANDONED(0x00000080L) 表示拥有信号量的线程再终止前未释放该信号量;
WAIT_OBJECT_0(0x00000000L) 表示等到了信号量;
WAIT_TIMEOUT(0x00000102L) 表示等待超时;
WAIT_FAILED((DWORD)0xFFFFFFFF) 表示该函数执行失败,用GetLastError()得到错误码; //释放信号量句柄
BOOL WINAPI ReleaseSemaphore(
_In_ HANDLE hSemaphore, //信号量对象句柄;
_In_ LONG lReleaseCount, //信号量释放的值,必须大于0;
_Out_opt_ LPLONG lpPreviousCount //前一次信号量值的指针,不需要可置为空;
);
返回值:成功返回非0;

Win32平台下源码

#include <iostream>
#include <windows.h>
using namespace std; HANDLE g_hSemaphore = NULL; //声明信号量变量 unsigned long WINAPI Fun(LPVOID lpParamter)
{
int iRunTime = 0;
//执行100次跳出
while(++iRunTime<100)
{
WaitForSingleObject(g_hSemaphore, INFINITE); //信号量值-1
cout << "Fun() is running!"<<endl;
ReleaseSemaphore(g_hSemaphore, 1, NULL); //信号量值+1
Sleep(10);
}
ExitThread(-1);
} int main()
{
//创建信号量对象
g_hSemaphore = CreateSemaphore(NULL //信号量的安全特性
, 1 //设置信号量的初始计数。可设置零到最大值之间的一个值
, 1 //设置信号量的最大计数
, NULL //指定信号量对象的名称
);
if(NULL == g_hSemaphore)
{
cout << "create hSemaphore failed! error_code:"<<GetLastError()<<endl;
return 0;
} int iRunTime = 0;
unsigned long ulThreadId = 0;
//创建一个子线程
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, &ulThreadId); //执行100次跳出
while(++iRunTime<100)
{
WaitForSingleObject(g_hSemaphore, INFINITE); //信号量值-1
cout << "main() is running, Thread id is " << ulThreadId <<endl;
ReleaseSemaphore(g_hSemaphore, 1, NULL); //信号量值+1
Sleep(10);
}
system("pause");
return 0;
}

执行结果: 
 
可见未对屏幕资源产生“争夺”的情况,达到线程同步的目的。

Linux平台

相关函数和头文件

int sem_init(sem_t *sem, int pshared, unsigned int value); 
1)pshared==0 用于同一多线程的同步; 
2)若pshared>0 用于多个相关进程间的同步(即由fork产生的); 
int sem_getvalue(sem_t *sem, int *sval); 
取回信号量sem的当前值,把该值保存到sval中。 
若有1个或更多的线程或进程调用sem_wait阻塞在该信号量上,该函数返回两种值: 
1) 返回0 
2) 返回阻塞在该信号量上的进程或线程数目 
linux采用返回的第一种策略。 
sem_wait(或sem_trywait)相当于P操作,即申请资源。 
int sem_wait(sem_t *sem); // 这是一个阻塞的函数 
测试所指定信号量的值,它的操作是原子的。 
若sem>0,那么它减1并立即返回。 
若sem==0,则睡眠直到sem>0,此时立即减1,然后返回; 
int sem_trywait(sem_t *sem); // 非阻塞的函数 
其他的行为和sem_wait一样,除了: 
若sem==0,不是睡眠,而是返回一个错误EAGAIN。 
sem_post相当于V操作,释放资源。 
int sem_post(sem_t *sem); 
把指定的信号量sem的值加1; 
呼醒正在等待该信号量的任意线程。

源码

#include <iostream>
#include <pthread.h>
#include <semaphore.h>
using namespace std; static sem_t g_semaphore;
static const int g_iRunTime = 5000; void* Fun(void* ptr)
{
int iRunTime = 0;
while(++iRunTime< g_iRunTime)
{
sem_wait(&g_semaphore);
cout<< "Fun() is running!" << endl;
sem_post(&g_semaphore);
usleep(100);
}
} int main()
{
pthread_t hHandle;
sem_init(&g_semaphore, 0, 1);
int iRet = pthread_create(&hHandle, NULL, Fun, NULL); //create a thread;
if(0 != iRet)
{
cout << "Create thread failed!" << endl;
}
sleep(1);
int iRunTime = 0;
while(++iRunTime<g_iRunTime)
{
sem_wait(&g_semaphore);
cout << "main is running!" << endl;
sem_post(&g_semaphore);
usleep(100);
}
pthread_join(hHandle, NULL);
return 0;
}

执行结果

 
达到同步效果!

关于Linux信号量

Linux信号量比Windows要复杂,上述例子只是使用了其中最常用的一种,还有许多其他种类的信号量,后期会补上一篇关于Linux信号量详解的内容。

C++多线程同步之Semaphore(信号量)的更多相关文章

  1. 线程间同步之 semaphore(信号量)

    原文地址:http://www.cnblogs.com/yuqilin/archive/2011/10/16/2214429.html semaphore 可用于进程间同步也可用于同一个进程间的线程同 ...

  2. python多线程同步机制Semaphore

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ Python 线程同步机制:Semaphore "" ...

  3. 多线程编程(一)-Semaphore(信号量)的使用

    Semaphore的介绍 单词Semaphore的中文含义就是信号.信号系统的意思,此类的主要作用就是限制线程并发的数量. 举个例子,一个屋子里有10个人,但只有一个窄门可以出去,这个窄门一次最多只能 ...

  4. Java核心-多线程-并发控制器-Semaphore信号量

    Semaphore是非常有用的一个多线程并发控制组件(Java还有CountDownLatch.CyclicBarrier.Exchanger多线程组件),它相当于是一个并发控制器,是用于管理信号量的 ...

  5. 【delphi】多线程同步之Semaphore

    另外两种多线程的同步方法 CriticalSection(临界区) 和 Mutex(互斥), 这两种同步方法差不多, 只是作用域不同; CriticalSection(临界区) 类似于只有一个蹲位的公 ...

  6. java 多线程 28 : 多线程组件之 Semaphore 信号量

    Semaphore是非常有用的一个组件,它相当于是一个并发控制器,是用于管理信号量的.构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问.我们需要控制并发的代码, ...

  7. Windows多线程同步系列之四-----信号量

    信号量说实话自己没怎么使用过.书上大概这样说,信号量设置一个资源访问计数.当该计数值大于0的时候,该信号量对象 为有信号状态,当该计数值等于0的时候,该信号量对象为无信号状态. 我们来查几个主要的AP ...

  8. c#多线程同步之Semaphore

    一提到Semaphore(信号量)的使用,还挺有意思的,它允许多个线程同时访问多个稀有资源,我立马想到银行的ATM机取钱的场景.看下面的代码: ); public static void StartT ...

  9. 多线程锁:Mutex互斥体,Semaphore信号量,Monitor监视器,lock,原子操作InterLocked

    Mutex类 “mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量.互斥量跟临界区中提到的Monitor很相似,只有拥有互斥对象的线程才具有访问资源的权限, ...

随机推荐

  1. Ascii vs. Binary Files

    Ascii vs. Binary Files Introduction Most people classify files in two categories: binary files and A ...

  2. 前端开发 —— js 常用工具函数(utilities)

    1. 时间 function getCurTime() { var date = new Date(); return date.toLocaleTimeString(); } date.toLoca ...

  3. top command-linux下用top命令查看cpu利用率超过100%

    1.  这里显示的所有的cpu加起来的使用率,说明你的CPU是多核,你运行top后按大键盘1看看,可以显示每个cpu的使用率,top里显示的是把所有使用率加起来;    2.查看CPU信息; cat ...

  4. C#/.NET 使用 CommandLineParser 来标准化地解析命令行

    CommandLineParser 是一款用于解析命令行参数的 NuGet 包.你只需要关注你的业务,而命令行解析只需要极少量的配置代码. 本文将介绍如何使用 CommandLineParser 高效 ...

  5. HDU 4666 最远曼哈顿距离

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4666 关于最远曼哈顿距离的介绍: http://blog.csdn.net/taozifish/ar ...

  6. tomcat源码阅读之容器(Container)

    一. 实现容器的接口是Container接口,Tomcat中共有四种类型的容器: 1.Engine:表示整个Catalina Servlet引擎: 2.Host:表示含有一个或者多个Context容器 ...

  7. 【转】每天一个linux命令(26):用SecureCRT来上传和下载文件

    原文网址:http://www.cnblogs.com/peida/archive/2012/11/28/2793181.html 用SSH管理linux服务器时经常需要远程与本地之间交互文件.而直接 ...

  8. Java中 @Override 的作用

    @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 可以当注释用,方便阅读: 编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如 ...

  9. h5 轻应用

    http://www.html5tricks.com/ http://open.weibo.com/wiki/%E8%BD%BB%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91 ...

  10. Flask请求处理流程(request)[待续]

    WSGI简介 WSGI(全称Web Server Gateway Interface),是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口,它封装了接受HTTP请求. ...