读者作家问题

发布于 2024-07-15 22:58:07 字数 817 浏览 5 评论 0原文

抱歉,如果我再次问同样的问题但想验证一下!

我有两个进程 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

问题:

  1. 是否需要在读卡器中加锁? 读者只会读取文件而不会更改它。 所以我想读卡器不需要锁。 想法? 不加锁的话某些情况下会出错吗?
  2. 我每次在读写过程中都会打开和关闭文件的句柄。 我认为这不是必需的。 我可以在构造函数中打开文件句柄,并在读取器和写入器的析构函数中关闭它。 但是当文件被用于写入时我可以读取它吗?

编辑:每次写入器在文件末尾写入 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:

  1. 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?
  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

画中仙 2024-07-22 22:58:07

答案是:当(且仅当)两个线程可以同时使用相同的共享资源时,锁定是必要的。 关于您的具体实现没有足够的信息,但我有几句话:

  1. 仅在写入期间锁定是没有意义的。 它只会增加一些开销,但不会阻止任何并发访问,直到读取器也被正确锁定为止。
  2. 如果修改与文件描述符连接的结构的文件操作没有以任何方式同步,则锁定是必要的。 当 P2 仍在读取时,P1 可能会开始写入文件。 如果读取和写入操作修改相同的系统结构而没有任何底层同步,您最终将得到损坏的数据。 很难说这里是否是这种情况,因为您没有提到您使用了哪个特定函数(库)。 文件操作在大多数系统上都是同步的,因此这应该不是问题。
  3. 从你写的关于“10字节信息部分”的内容来看,显式锁定似乎是没有必要的(除非#2不强加它)。 P1 产生数据量。 当数据准备好读取时,P1 通知 P2(通过事件;无论如何,事件传递应该在内部同步)。 P2知道它可以读取数据量,然后需要等待后续通知。 可能会发生在处理前一个通知之前发送后续通知的情况。 因此,事件需要以某种方式排队。 您还可以使用信号量代替事件通知。

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:

  1. Locking only during writing makes no sense. It only adds some overhead, but not prevent from any concurrent access until the reader is also correctly locked.
  2. Locking would be necessary if file operations which modify structures connected with the file's descriptors are not synchronized in any way. It may happen that P1 could start writing to the file when P2 is still reading. If reading and writing operations modify the same system structures without any underlying synchronization you will end up with corrupted data. It's hard to say if this is the case here because you didn't mention which particular function (libraries) you used. File operations are synchronized on most systems, so it shouldn't be a problem.
  3. From what you wrote about "10 bytes portions of information", the explicit locking seems to be not necessary (unless #2 doesn't impose it). P1 produces quantum of data. When the data is ready to be read P1 notifies P2 about that (by the event; event passing should be internally synchronized, anyhow). P2 knows that it could read quantum of data and then needs to wait for subsequent notification. It may happen that subsequent notification would be sent before previous one is handled. So, the events needs to be queued somehow. You can also use semaphore instead of events notification.
吾家有女初长成 2024-07-22 22:58:07

您需要读者获得锁定 - 事件的使用是无法替代的。 如果没有它,编写者可以在读取器代码中的任何位置开始编写。

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.

可可 2024-07-22 22:58:07

您绝对需要消费者锁定,以防止生产者在读者可以读取之前附加到文件。 想象一下这种情况:

Producer writes and signals
Consumer receives signal
Consumer opens the file
Producer fires again and writes another 10 bytes
Producer signals
Consumer reads the last 10 bytes
Consumer closes the file

接下来发生的情况取决于您的命名事件是手动重置还是自动重置。 如果它是自动重置,那么消费者将看到第二个信号,然后返回并再次读取相同的内容。 如果是手动重置,那么消费者将重置事件并错过生产者写入的最后一件事。

请注意,即使有了锁,如果生产者能够足够快地响应,您也会遇到竞争条件。 也就是说,生产者可能能够在消费者能够读取第一条记录之前将第二条记录放入文件中。

看来您这里拥有的是在文件中实现的 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:

Producer writes and signals
Consumer receives signal
Consumer opens the file
Producer fires again and writes another 10 bytes
Producer signals
Consumer reads the last 10 bytes
Consumer closes the file

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.

久夏青 2024-07-22 22:58:07
  1. 如果写入器可以随时开始写入,则确实需要锁定读取器中的互斥锁。 确保互斥锁是已命名的,以便 P2 可以打开它。

  2. 如果您在两个进程中使用 FileShare.ReadWrite 打开文件,则可以将其保持打开状态。

    如果

在阅读器中,您可能必须先查找到遇到 EOF 的位置,然后才能再次阅读。

如果您确定写入器总是追加并且您可以知道记录在哪里结束(例如,因为它们总是 10 个字节),并且您可以接受小的延迟,并且写入器总是写入完整的记录,那么您可以在不使用互斥体的情况下执行此操作和事件。 使用 FileShare.ReadWrite 打开文件,然后在阅读器中继续寻找同一位置并尝试读取您的记录,如果不能,请休眠一秒钟。 如果你能读完整个记录,你就得到了一个。 找出你的位置并循环返回以寻找该位置并尝试再次阅读。 这就是 tail -f 在 Unix 中的工作方式。

  1. 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.

  2. 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.

陈甜 2024-07-22 22:58:07

除了普通的同步功能外,您还可以使用文件更改通知 Windows 上的 API 用于等待文件更改。

Apart from normal synchronization functions, you can use the file change notification API on Windows to wait for file changes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文