读者作家问题
抱歉,如果我再次问同样的问题但想验证一下!
我有两个进程 P1 和 P2。
P1是一名作家(制作人)。
P2是读者(消费者)。
有一些共享内存或 P1 写入的文件,一旦 P1 写入,就应该通知 P2 进行读取。
现在根据我的理解,P1 的伪代码应该是
Open shared file Create a named event("Writedone") to signal write for P2 process Do some processing on file Mutex.Lock() Write to File Mutex.Unlock() Signal named Event. CloseHandle on file
Now in P2
Open handle to Shared file Open handle to named event WaitForSingleEvent on named event("Writedone") Read from file CloseHandle on file
问题:
- 是否需要在读卡器中加锁? 读者只会读取文件而不会更改它。 所以我想读卡器不需要锁。 想法? 不加锁的话某些情况下会出错吗?
- 我每次在读写过程中都会打开和关闭文件的句柄。 我认为这不是必需的。 我可以在构造函数中打开文件句柄,并在读取器和写入器的析构函数中关闭它。 但是当文件被用于写入时我可以读取它吗?
编辑:每次写入器在文件末尾写入 10 个字节,读取器应该读取写入器写入的最新 10 个字节。
Sorry if I am asking same question again but want to verify!
I have two processes P1 and P2.
P1 is a writer (Producer).
P2 is a reader (Consumer).
There is some shared memory or a file that P1 writes to and as soon as P1 writes, P2 should be notified for reading.
Now as per my understanding pseudocode for P1 should be
Open shared file Create a named event("Writedone") to signal write for P2 process Do some processing on file Mutex.Lock() Write to File Mutex.Unlock() Signal named Event. CloseHandle on file
Now in P2
Open handle to Shared file Open handle to named event WaitForSingleEvent on named event("Writedone") Read from file CloseHandle on file
Questions:
- Is it required to have locks in the reader? The reader will just read the file and not change it. So I guess no locks are required in the reader. Thoughts? Can it go wrong in some case without locks?
- I am opening and closing handles to the file every time during reading and writing. I think that is not required. I can open the file handle in the constructor and close it in the destructor of reader and writer. But can I read from the file when it is being used in writing?
EDIT: Everytime writer is writing 10 bytes at the end of File and reader is supposed to read the latest 10 bytes written by writer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
答案是:当(且仅当)两个线程可以同时使用相同的共享资源时,锁定是必要的。 关于您的具体实现没有足够的信息,但我有几句话:
The answer is: locking is necessary if (and only if) both threads can use the same shared resources at the same time. There isn't enough information about your specific implementation, but I have few remarks:
您需要读者获得锁定 - 事件的使用是无法替代的。 如果没有它,编写者可以在读取器代码中的任何位置开始编写。
You need the reader to get a lock - the use of events is no substitute. Without it, a writer could begin writing at any point in the reader code.
您绝对需要消费者锁定,以防止生产者在读者可以读取之前附加到文件。 想象一下这种情况:
接下来发生的情况取决于您的命名事件是手动重置还是自动重置。 如果它是自动重置,那么消费者将看到第二个信号,然后返回并再次读取相同的内容。 如果是手动重置,那么消费者将重置事件并错过生产者写入的最后一件事。
请注意,即使有了锁,如果生产者能够足够快地响应,您也会遇到竞争条件。 也就是说,生产者可能能够在消费者能够读取第一条记录之前将第二条记录放入文件中。
看来您这里拥有的是在文件中实现的 FIFO 队列,并且您依赖于消费者处理数据的能力比生产者创建数据的速度更快。 如果您可以保证这种行为,那么就没有问题。 否则,消费者将必须跟踪它上次读取的位置,以便知道下一步应该读取哪里。
You absolutely need the Consumer to lock in order to prevent the Producer from appending to the file before the reader can read. Imagine this scenario:
What happens next depends on if your named event is manual reset or auto reset. If it's auto reset, then the Consumer will see the second signal, and go back and read the same thing again. If it's manual reset, then the Consumer is going to reset the event and miss the last thing that the Producer wrote.
Note that even with the lock you have a race condition if the Producer can respond quickly enough. That is, the Producer might be able to put a second record into the file before the Consumer is able to read the first.
It appears that what you have here is a FIFO queue implemented in a file, and you're depending on the Consumer's ability to process data faster than the Producer can create it. If you can guarantee that behavior, then you're okay. Otherwise the Consumer will have to keep track of where it last read so that it knows where it should read next.
如果写入器可以随时开始写入,则确实需要锁定读取器中的互斥锁。 确保互斥锁是已命名的,以便 P2 可以打开它。
如果您在两个进程中使用 FileShare.ReadWrite 打开文件,则可以将其保持打开状态。
如果
在阅读器中,您可能必须先查找到遇到 EOF 的位置,然后才能再次阅读。
如果您确定写入器总是追加并且您可以知道记录在哪里结束(例如,因为它们总是 10 个字节),并且您可以接受小的延迟,并且写入器总是写入完整的记录,那么您可以在不使用互斥体的情况下执行此操作和事件。 使用 FileShare.ReadWrite 打开文件,然后在阅读器中继续寻找同一位置并尝试读取您的记录,如果不能,请休眠一秒钟。 如果你能读完整个记录,你就得到了一个。 找出你的位置并循环返回以寻找该位置并尝试再次阅读。 这就是 tail -f 在 Unix 中的工作方式。
You do need to lock the mutex in the reader, if the writer can start writing at any time. Make sure the mutex is a named one so P2 can open it.
If you open the file with FileShare.ReadWrite in both processes, you can leave it open.
In the reader, you may have to Seek to the place you hit EOF before you can read again.
If you are sure the writer is always appending and you can tell where a record ends (because they are always 10 bytes for example), and you can accept a small delay, and the writer always writes complete records, you can do this without mutexes and events at all. Open the file with FileShare.ReadWrite, and in the reader, keep seeking to the same place and trying to read your record, and sleep for a second if you couldn't. If you manage to read a whole record, you got one. Figure out your position and loop back to seek to that place and try to read again. This is kind of how tail -f works in Unix.
除了普通的同步功能外,您还可以使用文件更改通知 Windows 上的 API 用于等待文件更改。
Apart from normal synchronization functions, you can use the file change notification API on Windows to wait for file changes.