本文不没有任何知识可讲,只是帖上自己测试的结果。

想看底层原理的可以直接关闭。

不过对于急着要选方案的人,倒提供一些帮助。

先说一些无关紧要的废话:

====================================================================================================================================================

先说说为什么会有这篇文章。

我在做练习的时候,参考一些老代码,发现了CRITICAL_SECTION这个类型。以前没有用过。查了一下,三个要点:windows使用;互斥效果;比mutex快。

后来又翻了些网页查看两者的一些简介。很统一的结果,CRITICAL_SECTION比mutex快,而且Linux上没有类似的接口(注:可能是我搜索的方式不对,加上本人对Linux研究不多,所以没有找到)。

对于刚打算使用c++11制作全新技术接口版本的服务器的我来说,很遗憾啊,Linux没有。难道我只能用这种慢速的锁?而我又不想写太多差异化的代码,能用标准库最好,等到真的某个模块成为新能瓶颈的时候再针对某个模块在Linux上做差异处理。

所以我还是想使用标准库来完成这个事情。

于是,我搜索“CRITICAL_SECTION c++11”。

两篇很重要的文章出现在了搜索结果里,是因为这两篇文章而产生了本文。

https://stackoverflow.com/questions/23519630/are-there-c11-critical-sections

https://stackoverflow.com/questions/9997473/stdmutex-performance-compared-to-win32-critical-section

====================================================================================================================================================

第一篇文章的精要在:

虽然Linux上没有临界区这样的接口,而mutex又是需要陷入内核去处理的东西。但是呢这些都是规定,仅仅是为了兼容POSIX协议做的。而mutex慢主要是POSIX需要跨进程。但是呢,在不同的系统和版本上面,就可以有私人定制,就如同windows上的CRITICAL_SECTION。一旦我不再兼容POSIX,就可以做一些自己的花活。而同时在兼容POSIX的平台上,继续遵循POSIX的规定。

以上精要,你可以在第一个连接的第一个回复里面的追问里面得到。

这给我提供了一个很重要的信息:c++11是没有临界区这样的用法。而且mutex的跨进程也不是所有的系统和版本都需要的,仅仅是某些版本需要。在不需要的版本上std::mutex可能是有特殊的用法和优化可以媲美临界区。

总之,mutex和mutex不一样

有了这个想法,我决定自己写代码试试。

然而不幸的是,当我准备写的时候,我想,这种问题应该也会有其他人这样想吧,说不定能搜到呢?

在搜索结果里,我就看到了第二篇。

第二篇文章的精要在:

std::mutex慢。CRITICAL_SECTION更快。但是如果采用合理的方式来分割任务,两者可以达到几乎相同的效果。

第二篇文章是含有两个人的测试代码的。第一个人的测试代码是直接比对两种用法的时间差异。但是很遗憾,他使用的是vs2012。这个版本对c++11的支持并不算完美。第二个人的测试代码是将任务做了分割,分给不同的cpu,又延长了执行间隔,减少访问冲突。使用的是vs2013,这一传说中对c++11支持很完善的版本

看到这里,我有些冷,就不太想写测试代码了。原因是开发工具,人家已经更新到了一个合理的版本,其次在结构上进行了划分,而划分之后才打个平手。

似乎所有的结果都是唯一的。

但是!中间好几年了。万一有变化呢?即使没有,自己测试一下总归实在一些。所以还是自己做了个测试。结果很意外。

先说思路:

在同一进程中,开启4个线程,2个用std::mutext去抢,两个用CRITICAL_SECTION去抢;

两组方式各自使用自己组的变量;

只记录计算次数,不做结果正确判断;

以下是测试代码

 #include <iostream>
#include <mutex>
#include <thread>
#include <Windows.h>
#include <chrono> using namespace std; mutex g_Mutex_Lock, g_Mutex_finish;
CRITICAL_SECTION g_CS_Lock, g_CS_finish;
uint64_t g_Mutext_Num = -;
uint64_t g_CS_Num = -;
const int32_t g_Count = ;
once_flag g_Mutex_flag, g_CS_flag;
chrono::time_point<chrono::system_clock> g_Mutex_StartTime, g_CS_StartTime;
int32_t g_Mutex_Complete = ;
int32_t g_CS_Complete = ; uint64_t Calculate(uint64_t num, int index)
{
if (index % )
{
return (num / 0x5555) * 0xaaaa;
}
else
{
return (num / 0x6666) * 0x9999;
}
} void mutexTimeStart()
{
g_Mutex_StartTime = chrono::system_clock::now();
} void mutexCalculate()
{
call_once(g_Mutex_flag, mutexTimeStart); for (int i = ; i < g_Count; ++i)
{
g_Mutex_Lock.lock();
g_Mutext_Num = Calculate(g_Mutext_Num, i);
g_Mutex_Lock.unlock();
}
g_Mutex_finish.lock();
++g_Mutex_Complete;
if ( == g_Mutex_Complete)
{
chrono::duration<double> elapsed_seconds = chrono::system_clock::now() - g_Mutex_StartTime;
printf("mutex finished use: %f\n", elapsed_seconds.count());
}
g_Mutex_finish.unlock();
} void csTimeStart()
{
g_CS_StartTime = chrono::system_clock::now();
} void csCalculate()
{
call_once(g_CS_flag, csTimeStart);
for (int i = ; i < g_Count; ++i)
{
EnterCriticalSection(&g_CS_Lock);
g_CS_Num = Calculate(g_CS_Num, i);
LeaveCriticalSection(&g_CS_Lock);
}
EnterCriticalSection(&g_CS_finish);
++g_CS_Complete;
if ( == g_CS_Complete)
{
chrono::duration<double> elapsed_seconds = chrono::system_clock::now() - g_CS_StartTime;
printf("cs finished use: %f\n", elapsed_seconds.count());
}
LeaveCriticalSection(&g_CS_finish);
} void main()
{
InitializeCriticalSection(&g_CS_Lock);
InitializeCriticalSection(&g_CS_finish); thread t3(csCalculate);
t3.detach();
thread t4(csCalculate);
t4.detach(); thread t1(mutexCalculate);
t1.detach();
thread t2(mutexCalculate);
t2.detach(); int tStop;
cin >> tStop;
}

main.cpp

测试环境:win10企业版(已经更新到最新)+vs2015企业版+i7-6700HQ(2.6G×8)

64位release版结果:

图中除最后一个外,都是循环1千万次的结果。最后一个是10亿次的结果。

再上一个64位debug版的1亿次的截图(原谅我没有等带10亿次的结果,你们不知道,我测试1千万的结果是n秒。然后头绕一热直接跳了两级,一运行,发现没出结果,然后一算,就傻了,关掉减个0)。

无论前面有多少经历,无论多少推测。结果胜过一切,我可以继续安心的、开心的使用std继续进行我的练习了。

本次测试结果:

1、性能不是瓶颈,不要考虑太多。优化都是在原有的基础上逐步修改改出来的成果,不是动手的时候,脑子就有现成的方案。何况性能并没有走到瓶颈。

2、没有什么比电脑跑出来的结果更靠谱。毕竟电脑才是所有理论知识最终产物的执行者。

3、随时间的推移,技术在改良。使用通用的接口,每次技术更替,你也在享受免费的红利。

最后,如果有朋友发现我的代码中存在影响测试结果的错误,请留言指出。我不想自己错了,还误导别人。

mutex和CRITICAL_SECTION,互斥和临界区的更多相关文章

  1. pthread mutex 进程间互斥锁实例

    共享标志 定义 名称 描述 0 PTHREAD_PROCESS_PRIVATE 进程内互斥锁 仅可当前进程内共享 1 PTHREAD_PROCESS_SHARED 进程间互斥锁 多个进程间共享 第一个 ...

  2. Mutex 进程间互斥

    学习Mutex的心得,不一定对,先记录一下. 同步技术分为两大类,锁定和信号同步. 锁定分为:Lock.Monitor 信号同步分为:AutoResetEvent.ManualResetEvent.S ...

  3. Linux内核互斥锁--mutex

    一.定义: /linux/include/linux/mutex.h   二.作用及访问规则: 互斥锁主要用于实现内核中的互斥访问功能.内核互斥锁是在原子 API 之上实现的,但这对于内核用户是不可见 ...

  4. [Go] golang互斥锁mutex

    1.互斥锁用于在代码上创建一个临界区,保证同一时间只有一个goroutine可以执行这个临界区代码2.Lock()和Unlock()定义临界区 package main import ( " ...

  5. 十二 windows临界区,其他各种mutex

    一.windows临界区 类似于互斥量 == 临界区. 二.多次进入临界区 进入临界区(加锁): 离开临界区(解锁): 同一个线程中windows中相同临界区变量代表的临界区进入(entercirti ...

  6. 互斥量mutex简介

    互斥量又称互斥锁.互斥量是一个可以处于两态之一的变量:解锁和加锁. 简介 编辑 如果不需要信号量的计数能力,有时可以使用信号量的一个简化版本,称为互斥量(mutex).互斥量仅仅适用于管理共享资源或一 ...

  7. Linux的线程同步对象:互斥量Mutex,读写锁,条件变量

        进程是Linux资源分配的对象,Linux会为进程分配虚拟内存(4G)和文件句柄等 资源,是一个静态的概念.线程是CPU调度的对象,是一个动态的概念.一个进程之中至少包含有一个或者多个线程.这 ...

  8. Go 标准库 —— sync.Mutex 互斥锁

    Mutex 是一个互斥锁,可以创建为其他结构体的字段:零值为解锁状态.Mutex 类型的锁和线程无关,可以由不同的线程加锁和解锁. 方法 func (*Mutex) Lock func (m *Mut ...

  9. C++多线程同步之Mutex(互斥量)

    原文链接: http://blog.csdn.net/olansefengye1/article/details/53086141 一.互斥量Mutex同步多线程 1.Win32平台 相关函数和头文件 ...

随机推荐

  1. java在控制台输出空心正方形,菱形,空心菱形

     使用for和if打印一个空心正方形 /*思路:要想打印一个5x5的空心正方形,首先它的第一横行和最后一行都是填满的,需要全部遍历出来,第二三四行和只有左右两条边是出来的,中间部分为空的.因此在打印第 ...

  2. 自定义VS程序异常处理及调试Dump文件(一)

    自定义VS程序异常处理及调试Dump文件(一) 1. Dump文件 1. Dump文件介绍 Dump文件(Dump File),也叫转储文件,以.DMP为文件后缀.dump文件是进程在内存中的镜像文件 ...

  3. Java之面向对象概述,类,构造方法,static,主方法,对象

    一.面向对象概述 面向过程 "面向过程"(Procedure Oriented)是一种以过程为中心的编程思想.这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响 ...

  4. Java之面向对象例子(三) 多态,重写,重载,equals()方法和toString()方法的重写

    重写(继承关系) 子类得成员方法和父类的成员方法,方法名,参数类型,参数个数完全相同,这就是子类的方法重写了父类的方法. 重载 在一个类里有两个方法,方法名是完全一样的,参数类型或参数个数不同. 例子 ...

  5. 如何在web项目中添加javamelody monitoring 监控。

    1.在工程的maven pom中添加依赖javamelody-core <!-- monitoring监控 --><!-- https://mvnrepository.com/art ...

  6. (转)Spring 的 init-method 和 destory-method

    背景:今天在项目中看到spring中bean在初始化和注销时候的方法定义,之前没有用过这种方式,在此记录下,方便后期查看! 关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种: ...

  7. vue.js使用props在父子组件之间传参

    本篇文章是我参考官方文档整理的,供大家参考,高手勿喷! prop 组件实例的作用域是孤立的.这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据.要让子组件使用父组件的数据,我们需要通过子 ...

  8. 创建自己的代码片段(CodeSnippet)

    前言 工作中经常会写一些重复的代码片段,如自动属性.for循环.Action等等,针对这种情况,VisualStudio已经给我们提供了一个非常方便的功能--代码片段,是我们可以简单的输入几个字母就能 ...

  9. Hbase单机安装部署

    Hbase单机安装部署 http://blogxinxiucan.sh1.newtouch.com/2017/07/27/Hbase单机安装部署/ 下载Hbase Hbase官网下载地址 http:/ ...

  10. ExtJs的expand和collapse

    最近在研究ExtJs的窗口组件(Ext.window),关于扩展显示expand和折叠显示collapse的一点心得记录一下,以便后查. var win2 = new Ext.window({ id ...