读写者问题

image.png
image.png
image.png
image.png
image.png
Java参考

C++代码实现

  1. #include <iostream>
  2. #include <windows.h>
  3. #include <fstream>
  4. #define MAX_THREAD_NUM 64 //最大线程数
  5. #define INTE_PER_SEC 1000 //每秒时钟中断的数目
  6. #define MAX_FILE_NUM 32 //最大文件数目数
  7. #define MAX_STR_LEN 32 //字符串的长度
  8. using namespace std;
  9. int readcount = 0; //读者数目
  10. int writecount = 0; //写者数目
  11. CRITICAL_SECTION RP_Write; //临界资源
  12. CRITICAL_SECTION cs_Write;
  13. CRITICAL_SECTION cs_Read;
  14. struct ThreadInfo {
  15. int serial; //线程序号
  16. char entity; //线程类别(判断是读者还是写者线程)
  17. double delay; //线程延迟时间
  18. double persist; //线程读写操作时间
  19. };
  20. //读者优先<--->读者线程//
  21. void RP_ReaderThread(void *p) //P:读者线程信息
  22. {
  23. //互斥变量
  24. HANDLE h_Mutex;
  25. h_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex_for_readcount");
  26. DWORD wait_for_mutex; //等待互斥变量所有权
  27. DWORD m_delay; //延迟时间
  28. DWORD m_persist; //读文件持续时间
  29. int m_serial; //线程序号
  30. // 从参数中获得信息
  31. m_serial = ((ThreadInfo *) (p))->serial;
  32. m_delay = (DWORD) (((ThreadInfo *) (p))->delay * INTE_PER_SEC);
  33. m_persist = (DWORD) (((ThreadInfo *) (p))->persist * INTE_PER_SEC);
  34. Sleep(m_delay); //延迟等待
  35. cout << "Reader thread " << m_serial << " sents the reading require !" << endl;
  36. //等待互斥信号,保证对 ReadCount 的访问,修改互斥
  37. wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
  38. //读者数目增加
  39. readcount++;
  40. if (readcount == 1) {
  41. //第一个读者,等待资源
  42. EnterCriticalSection(&RP_Write);
  43. }
  44. ReleaseMutex(h_Mutex); //释放互斥信
  45. //读文件
  46. cout << "Reader thread " << m_serial << " begins to read file !" << endl;
  47. Sleep(m_persist);
  48. //退出线程
  49. cout << "Reader thread " << m_serial << " finished reading file !" << endl;
  50. //等待互斥信号,保证对 ReadCount 的访问,修改互斥
  51. wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
  52. //读者数目减少
  53. readcount--;
  54. if (readcount == 0) {
  55. //如果所有的读者读完,唤醒写者
  56. LeaveCriticalSection(&RP_Write);
  57. }
  58. ReleaseMutex(h_Mutex); //释放互斥信号
  59. }
  60. //P:写者线程信息
  61. void RP_WriterThread(void *p) {
  62. DWORD m_delay; //延迟时间
  63. DWORD m_persist; //写文件持续时间
  64. int m_serial; //线程序号
  65. // 从参数中获得信息
  66. m_serial = ((ThreadInfo *) (p))->serial;
  67. m_delay = (DWORD) (((ThreadInfo *) (p))->delay * INTE_PER_SEC);
  68. m_persist = (DWORD) (((ThreadInfo *) (p))->persist * INTE_PER_SEC);
  69. Sleep(m_delay);
  70. cout << "Writer thread " << m_serial << " sents the writing require !" << endl;
  71. //等待资源
  72. EnterCriticalSection(&RP_Write);
  73. //写文件
  74. cout << "Writer thread " << m_serial << " begins to write file !" << endl;
  75. Sleep(m_persist);
  76. //退出线程
  77. cout << "Writer thread " << m_serial << " finished writing file !" << endl;
  78. //释放资源
  79. LeaveCriticalSection(&RP_Write);
  80. }
  81. //读者优先处理函数
  82. void ReaderPriority(const char *fileName) {
  83. DWORD n_thread = 0; //线程数目
  84. DWORD thread_ID; //线程 ID
  85. DWORD wait_for_all; //等待所有线程结束
  86. //互斥对象
  87. HANDLE h_Mutex;
  88. h_Mutex = CreateMutex(NULL, FALSE, "mutex_for_readcount");
  89. //线程对象的数组
  90. HANDLE h_Thread[MAX_THREAD_NUM];
  91. ThreadInfo thread_info[MAX_THREAD_NUM];
  92. readcount = 0; //初始化 readcount
  93. InitializeCriticalSection(&RP_Write); //初始化临界区
  94. ifstream inFile;
  95. inFile.open(fileName);
  96. if (!inFile) {
  97. cout << "文件打开失败!" << endl;
  98. }
  99. cout << "读者优先:" << endl;
  100. while (inFile) {
  101. //读入每一个读者,写者的信息
  102. inFile >> thread_info[n_thread].serial;
  103. inFile >> thread_info[n_thread].entity;
  104. inFile >> thread_info[n_thread].delay;
  105. inFile >> thread_info[n_thread++].persist;
  106. inFile.get();
  107. }
  108. for (int i = 0; i < (int) (n_thread); i++) {
  109. if (thread_info[i].entity == 'R') {
  110. //创建读者进程
  111. h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (RP_ReaderThread), &thread_info[i], 0,
  112. &thread_ID);
  113. } else {
  114. //创建写线程
  115. h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (RP_WriterThread), &thread_info[i], 0,
  116. &thread_ID);
  117. }
  118. }
  119. //等待所有的线程结束
  120. wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
  121. cout << "All reader and writer have finished operating !" << endl;
  122. }
  123. //写者优先---读者线程
  124. //P:读者线程信息
  125. void WP_ReaderThread(void *p) {
  126. HANDLE print;
  127. print = CreateMutex(NULL, FALSE, LPCTSTR("mutex_for_print"));
  128. //互斥变量
  129. HANDLE h_Mutex1;
  130. h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex1");
  131. HANDLE h_Mutex2;
  132. h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex2");
  133. DWORD wait_for_mutex1; //等待互斥变量所有权
  134. DWORD wait_for_mutex2;
  135. DWORD m_delay; //延迟时间
  136. DWORD m_persist; //读文件持续时间
  137. int m_serial; //线程的序号
  138. //从参数中得到信息
  139. m_serial = ((ThreadInfo *) (p))->serial;
  140. m_delay = (DWORD) (((ThreadInfo *) (p))->delay * INTE_PER_SEC);
  141. m_persist = (DWORD) (((ThreadInfo *) (p))->persist * INTE_PER_SEC);
  142. Sleep(m_delay); //延迟等待
  143. DWORD wait_to_print = WaitForSingleObject(print, -1);
  144. cout << "Reader thread " << m_serial << " sents the reading require !" << endl;
  145. ReleaseMutex(print);
  146. wait_for_mutex1 = WaitForSingleObject(h_Mutex1, -1);
  147. //读者进去临界区
  148. EnterCriticalSection(&cs_Read);
  149. //阻塞互斥对象 Mutex2,保证对 readCount 的访问和修改互斥
  150. wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1);
  151. //修改读者的数目
  152. readcount++;
  153. if (readcount == 1) {
  154. // 如果是第 1 个读者,等待写者写完
  155. EnterCriticalSection(&cs_Write);
  156. }
  157. ReleaseMutex(h_Mutex2);// 释放互斥信号 Mutex2
  158. //让其他读者进去临界区
  159. LeaveCriticalSection(&cs_Read);
  160. ReleaseMutex(h_Mutex1);
  161. //读文件
  162. wait_to_print = WaitForSingleObject(print, -1);
  163. cout << "Reader thread " << m_serial << " begins to read file !" << endl;
  164. ReleaseMutex(print);
  165. Sleep(m_persist);
  166. //退出线程
  167. wait_to_print = WaitForSingleObject(print, -1);
  168. cout << "Reader thread " << m_serial << " finished reading file !" << endl;
  169. ReleaseMutex(print);
  170. //阻塞互斥对象 Mutex2,保证对 readcount 的访问,修改互斥
  171. wait_for_mutex1 = WaitForSingleObject(h_Mutex2, -1);
  172. readcount--;
  173. if (readcount == 0) {
  174. //最后一个读者,唤醒写者
  175. LeaveCriticalSection(&cs_Write);
  176. }
  177. ReleaseMutex(h_Mutex2); //释放互斥信号
  178. }
  179. //写者优先---写者线程
  180. //P:写者线程信息
  181. void WP_WriterThread(void *p) {
  182. DWORD wait_for_mutex3; //互斥变量
  183. DWORD m_delay; //延迟时间
  184. DWORD m_persist; //读文件持续时间
  185. int m_serial; //线程序号
  186. HANDLE h_Mutex3;
  187. h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex3");
  188. //从参数中获得信息
  189. m_serial = ((ThreadInfo *) (p))->serial;
  190. m_delay = (DWORD) (((ThreadInfo *) (p))->delay * INTE_PER_SEC);
  191. m_persist = (DWORD) (((ThreadInfo *) (p))->persist * INTE_PER_SEC);
  192. Sleep(m_delay); //延迟等待
  193. cout << "Writer thread " << m_serial << " sents the writing require !" << endl;
  194. wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
  195. writecount++; //修改写者数目
  196. if (writecount == 1) {
  197. EnterCriticalSection(&cs_Read);
  198. }
  199. ReleaseMutex(h_Mutex3);
  200. EnterCriticalSection(&cs_Write);
  201. cout << "Writer thread " << m_serial << " begins to write file !" << endl;
  202. Sleep(m_persist);
  203. cout << "Writer thread " << m_serial << " finished writing file !" << endl;
  204. LeaveCriticalSection(&cs_Write);
  205. wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
  206. writecount--;
  207. if (writecount == 0) {
  208. LeaveCriticalSection(&cs_Read);
  209. }
  210. ReleaseMutex(h_Mutex3);
  211. }
  212. //写者优先处理函数
  213. // fileName:文件名
  214. void WriterPriority(const char *fileName) {
  215. DWORD n_thread = 0;
  216. DWORD thread_ID;
  217. DWORD wait_for_all;
  218. HANDLE h_Mutex1;
  219. h_Mutex1 = CreateMutex(NULL, FALSE, "mutex1");
  220. HANDLE h_Mutex2;
  221. h_Mutex2 = CreateMutex(NULL, FALSE, "mutex2");
  222. HANDLE h_Mutex3;
  223. h_Mutex3 = CreateMutex(NULL, FALSE, "mutex3");
  224. HANDLE h_Thread[MAX_THREAD_NUM];
  225. ThreadInfo thread_info[MAX_THREAD_NUM];
  226. readcount = 0;
  227. writecount = 0;
  228. InitializeCriticalSection(&cs_Write);
  229. InitializeCriticalSection(&cs_Read);
  230. ifstream inFile;
  231. inFile.open(fileName);
  232. cout << "Writer Priority:" << endl;
  233. while (inFile) {
  234. inFile >> thread_info[n_thread].serial;
  235. inFile >> thread_info[n_thread].entity;
  236. inFile >> thread_info[n_thread].delay;
  237. inFile >> thread_info[n_thread++].persist;
  238. inFile.get();
  239. }
  240. for (int i = 0; i < (int) (n_thread); i++) {
  241. if (thread_info[i].entity == 'R') {
  242. //创建读者进程
  243. h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (WP_ReaderThread), &thread_info[i], 0,
  244. &thread_ID);
  245. } else if (thread_info[i].entity == 'W') {
  246. //创建写线程
  247. h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (WP_WriterThread), &thread_info[i], 0,
  248. &thread_ID);
  249. }
  250. }
  251. //等待所有的线程结束
  252. wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
  253. cout << "All reader and writer have finished operating !" << endl;
  254. }
  255. //主函数
  256. int main() {
  257. const char *file = "F:\\Study\\C++\\OS\\WR_EXP\\data.txt";
  258. char ch;
  259. cout<<endl;
  260. while (1) {
  261. cout << "--读者与写者问题--" << endl;
  262. cout << "---------------" << endl;
  263. cout << "| 1、读者优先 |" << endl;
  264. cout << "| 2、写者优先 |" << endl;
  265. cout << "| 3、退出 |" << endl;
  266. cout << "---------------" << endl;
  267. printf("请选择(1,2,3): ");
  268. do {
  269. ch = (char) getchar();
  270. } while (ch != '1' && ch != '2' && ch != '3');
  271. system("cls"); //执行清屏幕命令
  272. switch (ch) {
  273. case '1':
  274. ReaderPriority(file);
  275. break;
  276. case '2':
  277. WriterPriority(file);
  278. break;
  279. case '3':
  280. return 0;
  281. }
  282. cout << endl << "按任意键继续..." << endl;
  283. getchar();
  284. system("cls");
  285. }
  286. return 0;
  287. }