搜索
bottom↓
回复: 17

windows 多线程中是否可以用判断静态变量状态实现互斥

[复制链接]

出0入0汤圆

发表于 2018-5-30 20:14:46 | 显示全部楼层 |阅读模式
有两个线程,调用同一个函数,未避免函数中的写入操作被两线程同时调用,加了静态变量做保护,  第一个线程调用了该函数, 第二个线程需等待该函数执行完成才可调用,是否可以实现呢?  有没有什么问题?。

void  function1(int ii)
{
           static BOOL  Lock1=FALSE;
        while(Lock1==TRUE)
                sleep(1);
        Lock1=TRUE;
        Write_File( ii);
        Lock1=FALSE;
}

void Thread1()
{
        function1(1);
}

void Thread2()
{
        function1(2);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2018-5-30 20:35:11 来自手机 | 显示全部楼层
用一个api中的锁,代码量也不大。

出0入0汤圆

发表于 2018-5-30 20:38:55 来自手机 | 显示全部楼层
去看看孙鑫视频里面有一节课专门讲这个。

出0入70汤圆

发表于 2018-5-30 20:44:48 | 显示全部楼层
WaitForSingleObject(g_hMutex, INFINITE);

出0入0汤圆

发表于 2018-5-30 20:47:26 | 显示全部楼层
用标准线程互斥法

如果你的共用函数没有唯一需要操作的资源,则不用担心,windows会自动将函数重入的

如果有唯一需要保护的资源,你这样防不住的,你的保护操作需要几个分立的指令,中间任何时候都有可能被打断插入另外一个线程

出0入25汤圆

发表于 2018-5-30 20:48:00 来自手机 | 显示全部楼层
4楼正解,可以等待任何内核对象,包括mutex、event、file、thread、progress

出300入477汤圆

发表于 2018-5-30 21:15:58 来自手机 | 显示全部楼层
lswood 发表于 2018-5-30 20:48
4楼正解,可以等待任何内核对象,包括mutex、event、file、thread、progress

在同一个进程中用CRITICAL_SECTION最轻量级,也最快。如果没有别的特别需求,应当首选这个

出0入0汤圆

 楼主| 发表于 2018-5-30 21:20:49 | 显示全部楼层
我是否可以在子函数中使用这些标准线程互斥方法?   这样就不用在每个线程中,每处调用都写这么一段代码?

出300入477汤圆

发表于 2018-5-30 21:36:30 来自手机 | 显示全部楼层
四川李工 发表于 2018-5-30 21:20
我是否可以在子函数中使用这些标准线程互斥方法?   这样就不用在每个线程中,每处调用都写这么一段代码? ...

当然可以,而且这是最好的做法。其实你都不知道有多少个经常被你调用的库函数在内部是自带锁的,也不需要知道。
对于写库的人来说,如果他需要一把锁,就应当自己在内部做一个,不要把这个责任交给用户

出0入0汤圆

 楼主| 发表于 2018-5-30 21:57:25 | 显示全部楼层
看来我的方式不是很靠谱! 系统总共30多个线程,每几个小时就有一次数据没写成功。总结下来CRITICAL_SECTION   
WaitForSingleObject(g_hMutex, INFINITE);  等方式都可以,  是否确认这些互斥方式都可以写在子函数里面,而不需要每个线程调用处都写?   这问题答案 留给后面有这问题的网友吧

出0入0汤圆

发表于 2018-5-30 22:04:34 | 显示全部楼层
你最初的代码就是个自旋锁的雏形,改成atomic compare and exchange就能用。不过自旋锁里面最好不要做时间很长的动作,也不需要sleep,否则效率上反而不合算。用的合理的话,自旋锁效率远高于CriticalSection,你自己衡量吧。

出0入0汤圆

 楼主| 发表于 2018-5-30 22:15:45 | 显示全部楼层
我理解是 大概意思就是互斥锁 可以释放CPU资源,但是实时性差了点,  但是自旋锁占用CPU资源但是实时性好

出0入0汤圆

发表于 2018-5-30 22:19:15 | 显示全部楼层
四川李工 发表于 2018-5-30 22:15
我理解是 大概意思就是互斥锁 可以释放CPU资源,但是实时性差了点,  但是自旋锁占用CPU资源但是实时性好 ...

不。你要考虑切进内核态的开销,效率差异不是一星半点。

出0入0汤圆

 楼主| 发表于 2018-5-30 22:23:49 | 显示全部楼层
Scarlette 发表于 2018-5-30 22:19
不。你要考虑切进内核态的开销,效率差异不是一星半点。

您说的这句是什么意思?能否详细点?

出0入0汤圆

发表于 2018-5-30 22:32:25 | 显示全部楼层
发生任务调度的时候,都是要从用户态切入内核态处理的,开销非常大。Mutex任何操作都要切入内核态处理;Critical Section在EnterCriticalSection()被Block时,以及Resume(即被阻塞线程在其他线程LeaveCriticalSection后优先级反转切回CPU)时,都会发生内核态切换。

出0入0汤圆

发表于 2018-5-31 12:41:32 来自手机 | 显示全部楼层
你这段代码并不能实现你的功能。考虑多核情况,跑在两个核上的线程可能会同时进入while循环,同时判到锁未占用。单核情况,线程1判到锁未占用,在设置锁占用标志之前,可能会被操作系统抢占,切换到线程2,线程2同样发现锁未被占用,这样两个线程就同时获得锁了。要是不想使用操作系统提供的机制,你可以研究下CAS原子操作、peterson算法、面包店算法之类的方法。其实直接用操作系统的Critical Section好了,这货会先CAS一下,发现冲突了才会陷入内核阻塞,而实际上只要临界区足够小,冲突发生的机率极小,在CAS时就会获得锁,根本不会陷入内核休眠,所以不需要担心效率问题。

出30入25汤圆

发表于 2018-5-31 12:48:50 | 显示全部楼层
简单的变量不能当做多线程的“锁”来用。因为你不能保证对变量的操作不被线程调度打断。

就算是 i++ 这样简单的语句,尚且分为取值-自增-回写3个步骤,从而在多线程之下不能免于被打断的命运。

更何况你这个有这么多语句!

不明确指定一种“原子行为”(锁、原子计数等)的操作都不能用于线程间同步,再简单的也不行!!!

出0入0汤圆

发表于 2018-5-31 12:50:26 | 显示全部楼层
建议用标准的线程操作函数
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 09:08

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表