操作系统学习之多线程实战

题目:

 

在程序整个运行过程中,存在1个控制线程、1个生产者线程、以及若干个消费者线程。

  • 控制线程

即进程的主线程,用于控制生产、消费的行为。启动程序时,消费者线程的数量通过命令参数传入。

控制线程负责创建1个生产者线程和指定个数的消费者线程。

当接收到SIGUSR1信号后,控制线程负责结束生产者线程和消费者线程,然后退出。

控制线程在退出前,需要输出生产者已经生产的产品总数量、显示并对比WorkRecords中每个类型的产品的p_count值与c_count值(输出对比结果)。

  • 生产者线程

用于生成产品。产品数据只包含一个随机生成的标签值,标签值相同,则表示是同一类产品。

当一个产品生成时,需要更新WorkRecods:如果WorkRecords中没有该类产品的记录项,则需要添加一条记录项;如果WorkRecords中已经有该类产品的记录项,则更新该类产品的生产计数值(p_count)。

生产者与消费者之间通过队列来传递产品,队列的最大长度为50,如果队列已满,需要挂起等待。

在生产者线程结束时,将生产者已生产的产品总量作为线程的返回值。

  • 消费者线程

用于消费产品。当消费了一个产品时,需要更新WorkRecords中该类产品的消费计数值(c_count)。

  • WorkRecords

WorkRecords记录了所有已经产生过的产品种类。对于已经产生的每个产品种类,还记录了生成的数量和消费的数量。WorkRecordsHash表的形式组织。

要求:

使用POSIX标准的互斥量、条件变量等。

消费者线程要求定义为分离线程并进行命名。

代码中必须使用到互斥量的静态初始化和动态初始化。

“生产者已生产的产品总量”只能作为局部变量存在,不允许作为全局变量存在。

特别要注意临界区的保护。


设计实现思路

1、  控制线程、生产线程和消费线程个用一个文件来实现

2、  控制线程:

I、              完成共享变量的初始化,以及互斥变量、条件变量的管理;

II、            利用信号屏蔽字来使除控制线程以外的其他线程忽略终端的信号;

III、          利用pthread_kill来通知生产线程安全退出,利用cancel函数来通知消费者线程结束。

IV、          遍历hash以打印所有记录

3、  生产线程:

I、              利用sigaction实现对控制线程的信号反馈;

II、            在任何时候都通过遍历释放hash表来计算生产总数,避免使用全局变量

III、          采用队列为空或满两个条件变量来使生产者和消费者共享队列的访问

4、  消费线程:

I、              利用prtcl()函数实现线程命名,本程序中将所有消费者线程都命名为“consumer”


所遇问题及解决

1、             在控制线程中利用pthread_cancel来请求消费者线程退出时,由于取消点多且不稳定,导致消费者线程退出时为释放相关锁,造成死锁现象,最后通过使用全局变量来标志退出。

2、             在条件变量的使用中,多个线程等待时,不能确定哪个线程会被闲唤醒,这个根据系统资源而定,而且条件变量可能会被虚假条件唤醒,因而需要使用while循环不断判断条件的真假。





代码下载路径: https://download.csdn.net/download/qq_18631331/10458501