一个比较经典的同步问题:一个写/多个读

Necromancerr 2004-10-20 05:39:58
一个比较经典的同步问题:一个写/多个读,规则如下:

1.一个人在写时,其他人不允许写。
2.一个人在写时,其他人不允许读。
3.一个人在读时,其他人不允许写。
4.一个人在读时,其他人允许读。

允许使用Mutex、Event、Semaphore、CriticalSection等任意对象,求实现代码。


求实现代码。
...全文
535 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
guodong_77 2004-11-09
  • 打赏
  • 举报
回复
晕,都要代码啊,我有书,要不要撒都,^_^。
zhiguo_he 2004-11-09
  • 打赏
  • 举报
回复
我也要一份,谢谢先 zhiguo_he@163.com
zzxenjoy 2004-11-08
  • 打赏
  • 举报
回复
ding
allenq 2004-11-06
  • 打赏
  • 举报
回复
谢谢,我要一份, allenq@163.com
72193 2004-11-06
  • 打赏
  • 举报
回复
我也要 0459@sohu.com
linxy2002 2004-11-06
  • 打赏
  • 举报
回复
DentistryDoctor(雅克医生<医德,值得反思>)
也给我一份吧,我的 linxy_2002@yahoo.com.cn
ChinaOk 2004-11-06
  • 打赏
  • 举报
回复
第一类: 写者优先
条件:
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)

解2:如果读者数不固定,采用下面的算法:
设置三个互斥信号量:rwmutex 用于写者与其他读者/写者互斥的访问共享数据
rmutex 用于读者互斥的访问读者计数器readcount
nrmutex 用于写者等待已进入读者退出,所有读者退出前互斥写操作
var rwmutex, rmutex,nrmutex : semaphore := 1,1,1 ;
int readcount = 0;
cobegin
readeri begin // i=1,2,….
P(rwmutex);
P(rmutex);
Readcount++;
If (readcount == 1) P(nrmutex); //有读者进入,互斥写操作
V(rmutex);
V(rwmutex); // 及时释放读写互斥信号量,允许其它读、写进程申请资源
读数据;
P(rmutex);
Readcount--;
If (readcount == 0) V(nrmutex); //所有读者退出,允许写更新
V(rmutex);
End

Writerj begin // j = 1,2,….
P(rwmutex); // 互斥后续其它读者、写者
P(nrmutex); //如有读者正在读,等待所有读者读完
写更新;
V(nrmutex); //允许后续新的第一个读者进入后互斥写操作
V(rwmutex); //允许后续新读者及其它写者
End
Coend
ChinaOk 2004-11-06
  • 打赏
  • 举报
回复
写者优先
posedge 2004-11-05
  • 打赏
  • 举报
回复
核心编程
这本书里面很多的
lianglp 2004-11-04
  • 打赏
  • 举报
回复
void LeaveCriticalSectionState()//这个应写为:
{
::EnterCriticalSection(&csSetupCounterSection) ;
nReadCounter-- ;
if(nReadCounter == 0)
{
::LeaveCriticalSection(&sWriteSection) ;//如果为最后一个退出读状态,则关闭与写临界区的互拆
}
::LeaveCriticalSection(&csSetupCounterSection) ;
}
lianglp 2004-11-04
  • 打赏
  • 举报
回复
//假设临界区变量已初始化好。
int nReadCounter = 0 ;
CRITICAL_SECTION csWriteSection ;
CRITICAL_SECTION csSetupCounterSection ;



void EnterCriticalSectionState()
{
::EnterCriticalSection(&csSetupCounterSection) ;
if(nReadCounter == 0)
{
::EnterCriticalSection(&sWriteSection) ;//如果第一次读,则进入与写互拆的临界区
}
nReadCounter++ ;
::LeaveCriticalSection(&csSetupCounterSection) ;
}

void LeaveCriticalSectionState()
{
::EnterCriticalSection(&csSetupCounterSection) ;
nReadCounter-- ;
if(nReadCounter == 0)
{
::EnterCriticalSection(&sWriteSection) ;//如果为最后一个退出读状态,则关闭与写临界区的互拆
}
::LeaveCriticalSection(&csSetupCounterSection) ;
}

/////////////////////////////////////////////////
//以下一个为读线程,一个为写线程

DWORD __stdcall ReadThread(LPVOID pContext)//读线程
{
EnterCriticalSectionState() ;

//自己想做读的事情
...
ReadFunction() ;...


LeaveCriticalSectionState() ;
return NULL ;
}

DWORD __stdcall WriteThread(LPVOID pContext)//写线程
{
::EnterCriticalSection(&sWriteSection) ;

//自己想做写的事情
...
WriteFunction() ;

::LeaveCriticalSection(&sWriteSection) ;
return NULL ;
}

linxy2002 2004-11-04
  • 打赏
  • 举报
回复
帮忙顶,顺便接分
beyondtkl 2004-11-04
  • 打赏
  • 举报
回复
是哦 核心编程 里面有详细的说明 & 例子。。

里面代码 偶也有。。谁要的 发信息给我。。
xyg1985109 2004-11-04
  • 打赏
  • 举报
回复
DentistryDoctor(雅克医生<医德,值得反思>) :
能给我一份源程序嘛,我最近正在学习操作系统,刚好学完了线程,正准备看《windows核心编程》,能给我你的源代码让我学习一下嘛?因为我不知道我该怎么写那个框架!

也要向楼上的学习学习啊。。我现在还不是很熟悉api函数,有时候想要实现一些功能,得要差半天书!唉,学习中啊。。
icelight 2004-10-22
  • 打赏
  • 举报
回复
回楼上: 你的问题可用信号灯Semaphore解决。

DWORD threadA(void* pD)
{
int iID=(int)pD;
//在内部重新打开
HANDLE hCounterIn=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"sam sp 44");

for(int i=0;i<3;i++)
{
printf("%d wait for object\n",iID);
WaitForSingleObject(hCounterIn,INFINITE);
printf("\t\tthread %d : do database access call\n",iID);
Sleep(100);
printf("\t\tthread %d : do database access call end\n",iID);
ReleaseSemaphore(hCounterIn,1,NULL);
}
CloseHandle(hCounterIn);
return 0;
}
//in main function
{
//创建信号灯
HANDLE hCounter=NULL;
if( (hCounter=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"sam sp 44"))==NULL)
{
//如果没有其他进程创建这个信号灯,则重新创建
hCounter = CreateSemaphore(NULL,2,2,"sam sp 44");
}

//创建线程
HANDLE hThread[3];
CWinThread* pT1=AfxBeginThread((AFX_THREADPROC)threadA,(void*)1);
CWinThread* pT2=AfxBeginThread((AFX_THREADPROC)threadA,(void*)2);
CWinThread* pT3=AfxBeginThread((AFX_THREADPROC)threadA,(void*)3);
hThread[0]=pT1->m_hThread;
hThread[1]=pT2->m_hThread;
hThread[2]=pT3->m_hThread;
//等待线程结束
WaitForMultipleObjects(3,hThread,TRUE,INFINITE);

//关闭句柄
CloseHandle(hCounter);
}
xujungood 2004-10-21
  • 打赏
  • 举报
回复
我在windows下面写过一个程序,一个消费者,多个生产者,双方都判断变量bGoon,如果bGoon是false则跳出循环,否则循环。
但是只有把消费者线程和生产者线程都在循环中设置了一定延时才能安全推出,否则,当退出程序,关闭线程的时候,程序会死掉,
这是怎么回事啊?~
哪位高手能告诉我一下
flybusflybus 2004-10-21
  • 打赏
  • 举报
回复
实现代码
#include <Thread.h>

SNMPRWLock::SNMPRWLock()
{
};

bool SNMPRWLock::init(bool flag)
{
#if defined(WIN32)
hRWMutex = CreateEvent(NULL,FALSE,TRUE,NULL);
hReaderEve = CreateEvent(NULL,TRUE,FALSE,NULL);
bWriterFirst = flag;
iRefWriter = -1;
iRefReader = -1;

if(bWriterFirst)
{
hWriterEve = CreateEvent(NULL,TRUE,TRUE,NULL);
}
#else
pthread_rwlockattr_init(&attr);
pthread_rwlock_init(rw_lock, &attr)
#endif
return true;
};

void SNMPRWLock::fini()
{
#if defined(WIN32)
CloseHandle(hReaderEve);
CloseHandle(hRWMutex);
if(bWriterFirst)
{
CloseHandle(hWriterEve);
}
#else
pthread_rwlockattr_destroy(&attr);
pthread_rwlock_destroy(rw_lock);
#endif
};

void SNMPRWLock::acquire_read()
{
#if defined(WIN32)
if(bWriterFirst)
{
WaitForSingleObject(hWriterEve,INFINITE);
}

if(0 == InterlockedIncrement(&iRefReader))
{
WaitForSingleObject(hRWMutex, INFINITE);
SetEvent(hReaderEve);
};
WaitForSingleObject(hReaderEve,INFINITE);
#else
pthread_rwlock_rdlock(rw_lock);
#endif
};

void SNMPRWLock::acquire_write()
{
#if defined(WIN32)
if(bWriterFirst)
{
if(0 == InterlockedIncrement(&iRefWriter))
{
ResetEvent(hWriterEve);
}
}

WaitForSingleObject(hRWMutex, INFINITE);
#else
pthread_rwlock_wrlock(rw_lock);
#endif
};

void SNMPRWLock::Release()
{
#if defined(WIN32)
if(WAIT_TIMEOUT == WaitForSingleObject(hReaderEve,0))
{
SetEvent(hRWMutex);

if(bWriterFirst)
{
if(InterlockedDecrement(&iRefWriter) < 0 )
{
SetEvent(hWriterEve);
}
}
}
else if(InterlockedDecrement(&iRefReader) < 0)
{
ResetEvent(hReaderEve);
SetEvent(hRWMutex);
};
#else
pthread_rwlock_unlock(rw_lock);
#endif
};
flybusflybus 2004-10-21
  • 打赏
  • 举报
回复
我前几天正好写了一个,windows和solaris下都简单测试了,没有问题,也没有时间看,正好贴出来大家用,大家嗖嗖的目光帮我把把关(另外写锁优先的实现,windows下和solaris提供的天然写锁其实效果不尽相同,solaris下是通过提高线程优先级,而我的代码是通过代码逻辑,大家可以按需取舍)

#ifndef MYGOD
#define MYGOD

#if defined(WIN32)
#if _MSC_VER > 1000
#pragma once
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <pthread.h>
#endif

class SNMPRWLock
{
public:
SNMPRWLock(); //构造函数

private:
#if defined(WIN32)
HANDLE hRWMutex; //读写、写写互斥锁
HANDLE hReaderEve; //读事件
HANDLE hWriterEve; //写事件
long iRefReader; //读者引用记数
long iRefWriter; //写者引用记数
bool bWriterFirst; //通过写锁优先开关,避免提前优化带来的负面影
#else
pthread_rwlockattr_t attr; //读写锁属性对象
pthread_rwlock_t rw_lock; //读写锁
#endif

public:
bool init(bool); //初始化函数,参数表示是否需要写锁优先
void fini(); //回收函数
void acquire_read(); //加读锁
void acquire_write(); //加写锁
void Release(); //放锁
};

#endif
zdleek 2004-10-21
  • 打赏
  • 举报
回复
《Windows核心编程》经典著作
alexmayer 2004-10-21
  • 打赏
  • 举报
回复
搬个凳子坐下听讲!

顺便帮顶混分!
加载更多回复(7)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧