Windows API下的生产者-消费者同步实验

需积分: 31 9 下载量 162 浏览量 更新于2024-09-13 收藏 83KB DOC 举报
"生产者-消费者问题是多线程编程中的一种经典同步问题,涉及线程间的协作和资源的共享。本实验旨在通过Windows线程控制API实现生产者和消费者线程的同步控制,以解决资源的满和空状态管理。实验要求创建M个生产者线程和N个消费者线程,它们具有不同的延迟时间属性,按照先来先服务调度执行。当缓冲区满或空时,线程将被阻塞,并通过信号量机制进行唤醒。主要使用的Windows API包括CreateMutex、ReleaseMutex、CreateSemaphore和CreateThread等。" 在生产者-消费者问题中,核心目标是确保生产者不超量生产和消费者不提前消费。这里,系统设定了一个容量为K的缓冲区,用于存储产品。生产者线程负责生成数据并放入缓冲区,而消费者线程负责从缓冲区取出数据。为了保证线程安全,需要使用同步机制。 1. CreateMutex函数用于创建一个互斥量对象。互斥量是一种同步对象,同一时间只有一个线程能拥有它。在这里,生产者和消费者可能都会尝试访问缓冲区,互斥量可以防止多个线程同时操作缓冲区,确保数据的一致性。 2. ReleaseMutex函数用于释放对互斥量的持有。当线程完成对缓冲区的操作后,需要释放互斥量,以便其他线程可以获取并继续执行。 3. CreateSemaphore函数用于创建一个信号量对象。信号量用于控制对共享资源的并发访问,其计数值反映了资源的可用数量。在这里,信号量的初始计数值和最大计数值分别表示缓冲区的初始为空单元和最大容量。 4. CreateThread函数用于创建新的线程,它允许程序同时运行多个线程。生产者和消费者线程就是通过这个函数创建的,每个线程都有自己的延迟时间属性,决定了它们的执行顺序。 实验中,生产者线程在尝试向缓冲区添加产品时会检查信号量的计数值,如果计数值为0(即缓冲区满),则线程会被阻塞并等待;反之,生产者可以添加产品并将信号量减一。同样,消费者在尝试从缓冲区取出产品时,如果信号量的计数值大于0(即缓冲区非空),则可以取出产品并更新信号量。当缓冲区为空或满时,相应的线程会释放互斥量,让其他线程有机会执行。 通过这种同步机制,实验能够模拟真实环境中多线程的异步执行情况,有效地展示了生产者和消费者线程之间的交互。在输出中,可以看到哪个线程正在执行,哪个线程因为资源条件而被阻塞,从而直观地理解线程同步的概念及其在实际问题中的应用。
2014-03-11 上传
缓冲区的代码 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stream.h" int quit; #define DELAY_MAX 5000 //最大延时5000毫秒 #define IN_NUM (2) #define MAIN_STREAM (0) #define SLAVE_STREAM (1) void Init_Interface(int Msg_id) { int qid; if(ApproDrvInit(Msg_id)) exit(1); if (func_get_mem(&qid)) { ApproDrvExit(); exit(1); } } void Clean_Interface(void) { ApproInterfaceExit(); } static int alarm_rec_enable; static unsigned int deltime; static unsigned int GetTimeStamp(void) { struct timeval timeval; gettimeofday(&timeval, NULL); return (timeval.tv_sec * 1000) + (timeval.tv_usec + 500) / 1000;; } void *get_frame(void *arg) { FILE *filefd=NULL; char filename[80]; int ch=0; stream_rpos_t rpos; frame_head_t frame_head; int first_frame_type=0; int first_frame=0; char *frame_pos; char *data; unsigned int cur_time; printf("get ch %d stream\n", ch); memset(&rpos, 0, sizeof(rpos)); st_stream_getStartPos(ch, MAIN_STREAM, &rpos); st_stream_getOneFrame(ch, MAIN_STREAM, 10, &rpos); while(!quit) { if(alarm_rec_enable) { if(st_stream_getOneFrame(ch, MAIN_STREAM, 200, &rpos) <= 0) { usleep(10*1000); continue; } frame_pos = &rpos.p_buf_data[rpos.data_start_pos]; memcpy(&frame_head,&rpos.p_buf_data[rpos.data_start_pos],sizeof(frame_head)); data=frame_pos+sizeof(frame_head_t