在多线程编程中,如何实现同步?

时间:2021-10-02 18:28:43
说实话,在工作中没接触过多线程编程,但面试中经常会遇到。。。

如果多个线程同时对一段共享的表进行操作,如何保证多线程间同步呢?

先说说我的看法,使用信号量,获取表操作权的线程将信号量置位,其他线程发现信号量置位后将挂起(代码如何实现挂起?),表操作完成以后将信号量清位,其他线程重新申请表操作权(其他线程是如何知道信号量清位了?定时扫描?是否需要重新竞争表操作权?)

15 个解决方案

#1


信号量,互斥,临界区等都可以实现同步,不要让线程挂起,循环就好了

#2


WaitForSingleObject 等待信号量,并锁定信号量
ReleaseSemaphore 释放信号量

#3


引用 1 楼 franckson 的回复:
信号量,互斥,临界区等都可以实现同步,不要让线程挂起,循环就好了


应该是使用带超时的WaitForSingleObject循环,即不占用cpu资源,也不会造成线程死锁!

#4


我也没接触过



---------------------个性签名------------------------------------

编程论坛招聘版主
www.bbs.cxrs.net
欢迎加入

#5


你怎么创建线程?每套线程API都应该提供了相应的函数操作同步原语。

#6


引用 5 楼 Wolf0403 的回复:
你怎么创建线程?每套线程API都应该提供了相应的函数操作同步原语。

#7


临界区锁定数据访问,事件通知线程实现同步。

#8



1.Critical Section
A.速度快
B.不能用于不同进程
C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)

2.Mutex
A.速度慢
B.可用于不同进程
C.不能进行资源统计

3.Semaphore
A.速度慢
B.可用于不同进程
C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)

4.Event
A.速度慢
B.可用于不同进程
C.可进行资源统计

#9



//Use MFC in a Static Library

#include "stdafx.h"
#include <windows.h>
#include "stdio.h"
#include "afxmt.h"

int i=2;
CCriticalSection Cmysection;
DWORD WINAPI clientthread(LPVOID lpparam)
{
int num=(int)lpparam;
while(true)
{
Cmysection.Lock();
//可以使Cmysection.Lock()到Cmysection.Unlock();
//这段代码在同一时刻只允许一个线程操作
if(num==1)
printf("hthread1在操作\t");
else
printf("hthread2在操作\t");

Sleep(500);
i++;
printf("%d,%d\n",num,i);
Cmysection.Unlock();
}
return 0;
}

int main(int argc, char* argv[])
{
int num = 1;
HANDLE hthread1,hthread2;
DWORD dwthreadid;
char szBuff[MAX_PATH];

hthread1=CreateThread(NULL,0,clientthread,(LPVOID)num,0,&dwthreadid);
if(hthread1==NULL)
{
printf("fail55\n");
}


hthread2=CreateThread(NULL,0,clientthread,(LPVOID)(num+1),0,&dwthreadid);
if(hthread2==NULL)
{
printf("fail55\n");
}
gets(szBuff);

CloseHandle(hthread1);
CloseHandle(hthread2);
return 0;
}



#10


买本坦尼博姆的《操作系统设计与实现》认真看看吧。

#11


其他线程发现信号量置位后将挂起(代码如何实现挂起?)
其他线程是如何知道信号量清位了?定时扫描?
这些都是关键,哪位高人不吝赐教?
雁过留痕......

#12


引用 11 楼 wonderful_abc 的回复:
其他线程发现信号量置位后将挂起(代码如何实现挂起?) 
其他线程是如何知道信号量清位了?定时扫描? 
这些都是关键,哪位高人不吝赐教? 
雁过留痕......

waitforsingleobject之类的函数会“卡”在这里
至于信号量如何清位的,不必程序员知道啊

#13


引用 11 楼 wonderful_abc 的回复:
其他线程发现信号量置位后将挂起(代码如何实现挂起?) 
其他线程是如何知道信号量清位了?定时扫描? 
这些都是关键,哪位高人不吝赐教? 
雁过留痕......


例如2个线程 A和B

A,B刚开始运行的时候对信号量有共同的访问权限,就看谁快了,假如A线程先访问到信号量(由于信号量初始化为有信号状态),那么
wait或者waitforsingleobject函数运行完后,则将信号量设置为无信号状态,这时候如果线程B来访问受保护的代码段,它是访问不了的,只能等待(线程挂起,等待信号量),当线程A访问完了后,则需要对信号进行一个恢复设置状态,此时退出线程A,线程B此时发现信号量不为0了(至于如何发现,应该由系统来自动通知吧~~),那么信号B可以访问受保护代码了,过程同上拉```

至于你说的:1,当发现职位后确实要挂起,如何挂起,则是由系统来自动挂的,应该是交出该线程的行使权利,把CPU交给别的线程
              2:其他线成如何知道信号良职位了?信号量应该是一个系统中的核心对象,由操作系统来管理,当程序员对其置位以后,我想操作系统应该能检查得到,定时扫秒?应该是时间片的问题,每过一段时间就来看看这个信号量是否职位


嘿嘿,以上自己的认为,如有不正之处,请赐教

#14


建议楼主看候杰的<<win32 多线程程序设计>>, 里面讲的read/write锁的实现可以解决你的问题。

#15


...

#1


信号量,互斥,临界区等都可以实现同步,不要让线程挂起,循环就好了

#2


WaitForSingleObject 等待信号量,并锁定信号量
ReleaseSemaphore 释放信号量

#3


引用 1 楼 franckson 的回复:
信号量,互斥,临界区等都可以实现同步,不要让线程挂起,循环就好了


应该是使用带超时的WaitForSingleObject循环,即不占用cpu资源,也不会造成线程死锁!

#4


我也没接触过



---------------------个性签名------------------------------------

编程论坛招聘版主
www.bbs.cxrs.net
欢迎加入

#5


你怎么创建线程?每套线程API都应该提供了相应的函数操作同步原语。

#6


引用 5 楼 Wolf0403 的回复:
你怎么创建线程?每套线程API都应该提供了相应的函数操作同步原语。

#7


临界区锁定数据访问,事件通知线程实现同步。

#8



1.Critical Section
A.速度快
B.不能用于不同进程
C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)

2.Mutex
A.速度慢
B.可用于不同进程
C.不能进行资源统计

3.Semaphore
A.速度慢
B.可用于不同进程
C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)

4.Event
A.速度慢
B.可用于不同进程
C.可进行资源统计

#9



//Use MFC in a Static Library

#include "stdafx.h"
#include <windows.h>
#include "stdio.h"
#include "afxmt.h"

int i=2;
CCriticalSection Cmysection;
DWORD WINAPI clientthread(LPVOID lpparam)
{
int num=(int)lpparam;
while(true)
{
Cmysection.Lock();
//可以使Cmysection.Lock()到Cmysection.Unlock();
//这段代码在同一时刻只允许一个线程操作
if(num==1)
printf("hthread1在操作\t");
else
printf("hthread2在操作\t");

Sleep(500);
i++;
printf("%d,%d\n",num,i);
Cmysection.Unlock();
}
return 0;
}

int main(int argc, char* argv[])
{
int num = 1;
HANDLE hthread1,hthread2;
DWORD dwthreadid;
char szBuff[MAX_PATH];

hthread1=CreateThread(NULL,0,clientthread,(LPVOID)num,0,&dwthreadid);
if(hthread1==NULL)
{
printf("fail55\n");
}


hthread2=CreateThread(NULL,0,clientthread,(LPVOID)(num+1),0,&dwthreadid);
if(hthread2==NULL)
{
printf("fail55\n");
}
gets(szBuff);

CloseHandle(hthread1);
CloseHandle(hthread2);
return 0;
}



#10


买本坦尼博姆的《操作系统设计与实现》认真看看吧。

#11


其他线程发现信号量置位后将挂起(代码如何实现挂起?)
其他线程是如何知道信号量清位了?定时扫描?
这些都是关键,哪位高人不吝赐教?
雁过留痕......

#12


引用 11 楼 wonderful_abc 的回复:
其他线程发现信号量置位后将挂起(代码如何实现挂起?) 
其他线程是如何知道信号量清位了?定时扫描? 
这些都是关键,哪位高人不吝赐教? 
雁过留痕......

waitforsingleobject之类的函数会“卡”在这里
至于信号量如何清位的,不必程序员知道啊

#13


引用 11 楼 wonderful_abc 的回复:
其他线程发现信号量置位后将挂起(代码如何实现挂起?) 
其他线程是如何知道信号量清位了?定时扫描? 
这些都是关键,哪位高人不吝赐教? 
雁过留痕......


例如2个线程 A和B

A,B刚开始运行的时候对信号量有共同的访问权限,就看谁快了,假如A线程先访问到信号量(由于信号量初始化为有信号状态),那么
wait或者waitforsingleobject函数运行完后,则将信号量设置为无信号状态,这时候如果线程B来访问受保护的代码段,它是访问不了的,只能等待(线程挂起,等待信号量),当线程A访问完了后,则需要对信号进行一个恢复设置状态,此时退出线程A,线程B此时发现信号量不为0了(至于如何发现,应该由系统来自动通知吧~~),那么信号B可以访问受保护代码了,过程同上拉```

至于你说的:1,当发现职位后确实要挂起,如何挂起,则是由系统来自动挂的,应该是交出该线程的行使权利,把CPU交给别的线程
              2:其他线成如何知道信号良职位了?信号量应该是一个系统中的核心对象,由操作系统来管理,当程序员对其置位以后,我想操作系统应该能检查得到,定时扫秒?应该是时间片的问题,每过一段时间就来看看这个信号量是否职位


嘿嘿,以上自己的认为,如有不正之处,请赐教

#14


建议楼主看候杰的<<win32 多线程程序设计>>, 里面讲的read/write锁的实现可以解决你的问题。

#15


...