0

我有一个比较笼统的问题,请指教。

我有一个小服务程序。

这个 servlet 有私有字段。

私有字段是一种元数据的东西(公共类元数据{//bla-bla-bla})。

处理GET请求时,此元数据用于执行某些操作。

我想在同一个 servlet 中实现 POST 方法。用户上传文件并更新元数据字段。

问题:使用一个 servlet 实例在多个 web 线程之间共享元数据对象并发访问此私有字段。POST 方法操作(更新元数据对象)会导致元数据状态不一致,并发 GET 请求可能会失败。

问题:在 GET 请求运行时更新元数据对象的最佳方法是什么?

虚拟解决方案

  1. 在每个 GET 请求期间,一开始

  2. 同步元数据对象并将其克隆在一个块中,然后释放它。

  3. 并发 GET 请求与一致的元数据对象的克隆版本一起使用。

  4. 在每个 POST 请求期间。

  5. 同步元数据对象并更新其字段。

  6. 释放元数据对象。

请建议或批评。

4

1 回答 1

1

在 Metadata 类中使用同步方法 set 和 get 很好,但如果您有多个阅读器和(很多)较少的编写器,可能会减慢您的 Web 应用程序:

Java synchronized 关键字用于获取对象的排他锁。当一个线程获取一个对象的锁用于读取或写入时,其他线程必须等待直到该对象上的锁被释放。想象一个场景,有许多读取器线程频繁读取共享数据,而只有一个写入器线程更新共享数据。读取时不必专门锁定对共享数据的访问,因为多个读取操作可以并行完成,除非有写入操作。

(摘自那篇不错的帖子

因此,在某些情况下,使用多读单写策略在性能方面可能会更好,这在同一个 Java5 ReadWriteLock接口文档中也有解释:

与互斥锁相比,读写锁在访问共享数据时允许更高级别的并发性。它利用了这样一个事实:虽然一次只有一个线程(写入线程)可以修改共享数据,但在许多情况下,任意数量的线程可以同时读取数据(因此读取线程)。理论上,使用读写锁所允许的并发性的增加将导致比使用互斥锁的性能提高。在实践中,这种并发性的增加只有在多处理器上才能完全实现,而且只有在共享数据的访问模式合适的情况下。

读写锁是否会比使用互斥锁提高性能取决于数据被读取与修改相比的频率、读写操作的持续时间以及数据的争用——即即,将尝试同时读取或写入数据的线程数。例如,最初填充了数据并随后不经常修改但经常被搜索(例如某种目录)的集合是使用读写锁的理想候选者。但是,如果更新变得频繁,则数据大部分时间都被排他锁定,并且并发性几乎没有增加。更远,如果读取操作太短,则读写锁实现的开销(本质上比互斥锁更复杂)会主导执行成本,特别是因为许多读写锁实现仍然通过一小部分序列化所有线程的代码。最终,只有分析和测量才能确定读写锁的使用是否适合您的应用程序。

一个现成的实现是ReentrantReadWriteLock

查看上一篇文章,了解如何使用它的不错的教程。

于 2012-11-12T21:45:50.550 回答