北邮 操作系统 实验一 进程同步.docx
- 文档编号:15723887
- 上传时间:2023-07-07
- 格式:DOCX
- 页数:21
- 大小:35.55KB
北邮 操作系统 实验一 进程同步.docx
《北邮 操作系统 实验一 进程同步.docx》由会员分享,可在线阅读,更多相关《北邮 操作系统 实验一 进程同步.docx(21页珍藏版)》请在冰点文库上搜索。
北邮操作系统实验一进程同步
实验一进程同步
1.实习要求
在Windows环境下,创建一个包含n个线程的控制进程。
用这n个线程来表示n
个读者或写者。
每个线程按相应测试数据文件的要求,进行读写操作。
请用信号量
机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制:
1)写-写互斥;
2)读-写互斥;
3)读-读允许;
读者优先的附加限制:
如果一个读者申请进行读操作时已有另一读者正在进行读操作,
则该读者可直接开始读操作。
写者优先的附加限制:
如果一个读者申请进行读操作时已有另一写者在等待访问共享资
源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:
要求在每个线程创建、发出读写操作申请、开始读写操作和结束读
写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。
2.测试数据文件格式
测试数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写
操作的开始时间和持续时间。
每行测试数据包括四个字段,各字段间用空格分隔。
第一字段
为一个正整数,表示线程序号。
第一字段表示相应线程角色,R表示读者是,W表示写者。
第二字段为一个正数,表示读写操作的开始时间。
线程创建后,延时相应时间(单位为秒)
后发出对共享资源的读写申请。
第三字段为一个正数,表示读写操作的持续时间。
当线程读
写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
下面是一个测试数据文件的例子:
1R35
2W45
3R52
4R65
5W5.13
3.本实验的相关知识
3.1进程
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。
它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
3.2线程
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。
一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
由于线程之间的相互制约,致使线程在运行中呈现出间断性。
线程也有就绪、阻塞和运行三种基本状态。
每一个程序都至少有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。
在单个程序中同时运行多个线程完成不同的工作,称为多线程。
3.3 同步和互斥
进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。
通常的情况是两个或两个以上的进程需要同时访问某个共享变量。
我们一般将发生能够问共享变量的程序段成为临界区。
两个进程不能同时进入临界区,否则就会导致数据的不一致,产生与时间有关的错误。
解决互斥问题应该满足互斥和公平两个原则,即任意时刻只能允许一个进程处于同一共享变量的临界区,而且不能让任一进程无限期地等待。
互斥问题可以用硬件方法解决;也可以用软件方法。
同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。
在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。
少数情况是指可以允许多个访问者同时访问资源。
4.函数
4.1线程控制
4.1.1CreateThread
完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。
HANDLECreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes,//SD
DWORDdwStackSize,//initialstacksize
LPTHREAD_START_ROUTINElpStartAddress,//thread
function
LPVOIDlpParameter,//threadargument
DWORDdwCreationFlags,//creationoption
LPDWORDlpThreadId//threadidentifier
);
4.1.2ExitThread
用于结束当前线程。
VOIDExitThread(
DWORDdwExitCode//exitcodeforthisthread
);
4.1.3Sleep
可在指定的时间内挂起当前线程。
VOIDSleep(
DWORDdwMilliseconds//sleeptime
);
4.1.4信号量控制:
CreateMutex
创建一个互斥对象,返回对象句柄;
HANDLECreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes,//SD
BOOLbInitialOwner,//initialowner
LPCTSTRlpName//objectname
);
4.1.5OpenMutex
打开并返回一个已存在的互斥对象句柄,用于后续访问;
HANDLEOpenMutex(
DWORDdwDesiredAccess,//access
BOOLbInheritHandle,//inheritanceoption
LPCTSTRlpName//objectname
);
4.1.6ReleaseMutex
释放对互斥对象的占用,使之成为可用。
BOOLReleaseMutex(
HANDLEhMutex//handletomutex
);
4.1.7WaitForSingleObject
可在指定的时间内等待指定对象为可用状态;
DWORDWaitForSingleObject(
HANDLEhHandle,//handletoobject
DWORDdwMilliseconds//time-outinterval
);
4.2程序分析
4.2.1读者优先模式:
读者进程:
RP_ReaderThread()
P(mutex);
read_count++;
if(read_count==1)//如果有读者开始读操作,则停止写操作
P(&RP_Write);
V(mutex);
-----------------------------------------------------
读临界区……
-----------------------------------------------------
P(mutex);
read_count--;
if(read_count==0)//所有读者读操作完毕,开放写操作
V(&RP_Write);
V(mutex);
写者进程:
RP_WriterThread函数的实现如下:
P(&RP_Write);
---------------------------------------------
写临界区……
---------------------------------------------
V(&RP_Write);
4.2.2写者优先模式:
读者进程:
WP_ReaderThread()
P(mutex1);
P(&cs_Read);
P(mutex2);
read_count++;
if(read_count==1)//有读者开始读操作,写者等待
P(&cs_Write);
V(mutex2);
V(&cs_Read);
V(mutex1);
--------------------------------------
读临界区……
--------------------------------------
P(mutex2);
read_count--;
if(read_count==0)//所有读者完成读操作,开放写操作
V(&cs_Write);
V(mutex2);
写者进程:
WP_WriterThread()
P(mutex3);
write_count++;
if(write_count==1)//有写者要进行操作,之后的读者全部暂停,直到写者完成操作
P(&cs_Read);
V(mutex3);
P(&cs_Write);
----------------------------------
写临界区……
----------------------------------
V(&cs_Write);
P(mutex3);
write_count--;
if(write_count==0)//所有写者完成操作,开放读者读操作
V(&cs_Read);
V(mutex3);
4.3代码
头文件
#include"windows.h"
#include
#include
#include
#include
#include
#include
#defineREADER'R'//读者
#defineWRITER'W'//写者
#defineINTE_PER_SEC1000//每秒时钟中断数目
#defineMAX_THREAD_NUM64//最大线程数目
#defineMAX_FILE_NUM32//最大数据文件数目
#defineMAX_STR_LEN32//字符串长度
全局函数
intreadcount=0;//读者数目
intwritecount=0;//写者数目
CRITICAL_SECTIONRP_Write;//临界区
CRITICAL_SECTIONcs_Write;
CRITICAL_SECTIONcs_Read;
线程结构
structThreadInfo
{
intserial;//线程序号
charentity;//线程类别(判断是读者线程还是写者线程)
doubledelay;//线程延迟
doublepersist;//线程读写操作持续时间
};
//读者优先-读者线程
//p:
读者线程信息
voidRP_ReaderThread(void*p)
{
//互斥变量
HANDLEh_Mutex;
h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
DWORDwait_for_mutex;//等待互斥变量所有权
DWORDm_delay;//延迟时间
DWORDm_persist;//读文件持续时间
intm_serial;//线程序号
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Readerthread%dsentsthereadingrequire.\n",m_serial);
//等待互斥信号,保证对readcount的访问、修改和互斥
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//P操作
//读者数目增加
readcount++;
if(readcount==1)
{
//读第一个读者,等待资源
EnterCriticalSection(&RP_Write);
}
ReleaseMutex(h_Mutex);//V操作
printf("Readerthread%dbeginstoreadfile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Readerthread%dfinishedreadingfile.\n",m_serial);
//等待互斥信号,保证对readcount的访问、修改互斥
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//P操作
//读者数目减少
readcount--;
if(readcount==0)
{
//如果读者全部读完,唤醒写者
LeaveCriticalSection(&RP_Write);
}
ReleaseMutex(h_Mutex);//V操作
}
//读者优先-写者线程
//写者线程信息
voidRP_WriterThread(void*p)
{
DWORDm_delay;//延迟时间
DWORDm_persist;//写文件持续时间
intm_serial;//线程序号
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Writerthread%dsentsthewritingrequire.\n",m_serial);
//等待资源
EnterCriticalSection(&RP_Write);
//写文件
printf("Writerthread%dbeginstowritetothefile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Writerthread%dfinishedwritingtothefile.\n",m_serial);
//释放资源
LeaveCriticalSection(&RP_Write);
}
//读者优先处理函数
//file:
文件名
voidReaderPriority(char*file)
{
DWORDn_thread=0;//线程数目
DWORDthread_ID;//线程ID
DWORDwait_for_all;//等待所有线程结束
//互斥对象
HANDLEh_Mutex;
h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount");
//线程对象的数组
HANDLEh_Thread[MAX_THREAD_NUM];
ThreadInfothread_info[MAX_THREAD_NUM];
readcount=0;//初始化readcount
InitializeCriticalSection(&RP_Write);//初始化临界区
ifstreaminFile;
inFile.open(file);//打开文件
printf("ReaderPriority:
\n\n");
while(inFile)
{
//读入每一个读者、写者的信息
inFile>>thread_info[n_thread].serial;
inFile>>thread_info[n_thread].entity;
inFile>>thread_info[n_thread].delay;
inFile>>thread_info[n_thread++].persist;
inFile.get();
}
for(inti=0;i<(int)(n_thread);i++)
{
if(thread_info[i].entity==READER||thread_info[i].entity=='r')
{
//创建读者进程
h_Thread[i]=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)(RP_ReaderThread),
&thread_info[i],
0,&thread_ID);
}
else{
//创建写者进程
h_Thread[i]=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)(RP_WriterThread),
&thread_info[i],
0,&thread_ID);
}
}
//等待所有线程结束
wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);
printf("Allreaderandwriterhavefinishedoperating.\n");
}
//写者优先--读者进程
//p:
读者线程信息
voidWP_ReaderThread(void*p)
{
//互斥变量
HANDLEh_mutex1;
h_mutex1=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex1");
HANDLEh_mutex2;
h_mutex2=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex2");
DWORDwait_for_mutex1;//等待互斥变量所有权
DWORDwait_for_mutex2;
DWORDm_delay;//延迟时间
DWORDm_persist;//读文件持续时间
intm_serial;//线程序号
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Readerthread%dsentsthereadingrequire.\n",m_serial);
wait_for_mutex1=WaitForSingleObject(h_mutex1,-1);//P操作
//进入读者临界区
EnterCriticalSection(&cs_Read);//P操作
//阻塞互斥对象mutex2,保证对readcount的访问、修改互斥
wait_for_mutex2=WaitForSingleObject(h_mutex2,-1);//P操作
//修改读者数目
readcount++;
if(readcount==1)
{
//如果是第一个读者,等待写者写完
EnterCriticalSection(&cs_Write);
}
ReleaseMutex(h_mutex2);//V操作
//让其他读者进入临界区
LeaveCriticalSection(&cs_Read);
ReleaseMutex(h_mutex1);//V操作
//读文件
printf("Readerthread%dbeginstoreadfile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Readerthread%dfinishedreadingfile.\n",m_serial);
//阻塞互斥对象mutex2,保证对readcount的访问、修改互斥
wait_for_mutex2=WaitForSingleObject(h_mutex2,-1);//P操作
readcount--;
if(readcount==0)
{
//如果所有读者读完,唤醒写者
LeaveCriticalSection(&cs_Write);
}
ReleaseMutex(h_mutex2);//V操作
}
//写者优先--写者线程
//p:
写者线程信息
voidWP_WriterThread(void*p)
{
DWORDwait_for_mutex3;
DWORDm_delay;//延迟时间
DWORDm_persist;//写文件持续时间
intm_serial;//线程序号
//互斥对象
HANDLEh_mutex3;
h_mutex3=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex3");
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Writerthread%dsentsthewritingrequire.\n",m_serial);
//阻塞互斥对象mutex3,保证对writecount的访问、修改互斥
wait_for_mutex3=WaitForSingleObject(h_mutex3,-1);//P操作
//修改写者数目
writecount++;
if(writecount==1)
{
//第一个写者,等待读者读完
EnterCriticalSection(&cs_Read);
}
ReleaseMutex(h_mutex3);//V操作
//进入写者临界区
EnterCriticalSection(&cs_Write);
//写文件
printf("Writerthread%dbeginstowritetothefile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Writerthread%dfinishedwritingtothefile.\n",m_serial);
//离开临界区
LeaveCriticalSection(&cs_Write);
//阻塞互斥对象mutex3,保证对writecount的访问、修改互斥
wait_for_mutex3=WaitForSingleObject(h_mutex3,-1);//P操作
writecount--;
if(writecount==0)
{
//写者写完,读者可以读
LeaveCriticalSection(&
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北邮 操作系统 实验一 进程同步 实验 进程 同步