【问题标题】:setting servlet context attribute in a theadsafe manner以安全的方式设置 servlet 上下文属性
【发布时间】:2016-05-25 02:08:06
【问题描述】:

我正在开发一个 Web 应用程序,其中名为 CheckURL 的 servlet 将在其 init 方法中从 xml 文件中读取一些数据,并将该 xml 中的节点列表放入 servletcontext 中。因此,到达此 servlet 的每个请求都不必一次又一次地从 xml 中读取数据。它可以从 servletcontext 中获取节点列表。应用程序中有另一个 servlet 用于更新 xml,如果更新了 xml,我将更新 servletcontext nodelist 变量。

因此,在这种情况下,我希望进行同步以确保在写入 xml 时,应阻止从 servletcontext 节点列表中读取的任何内容。如果不是,它可能正在读取不是最新的数据。

为了实现这一点,我想知道我应该使用哪个同步级别。我应该在 servletcontext 对象上同步,还是应该在 servlet 上下文中的元素集上同步,或者我应该在 servlet 类实例上同步。

【问题讨论】:

  • ServetContext上同步。
  • @EJP 我想知道,在我看来,在 servletcontext 上同步会减慢应用程序的速度。由于 servletcontext 对象可能也已被其他 servlet 使用,并且我对 nodelist 的读取或写入操作不应阻止对存储在 servlet 上下文中的其他变量的读取和写入。
  • 你想多了。它只会显示应用程序中也在同一事物上同步的那些部分,并且仅显示在同步块中花费的时间量。更新上下文变量真正需要多长时间?

标签: java mysql multithreading jakarta-ee concurrency


【解决方案1】:

出于性能原因,建议同步范围尽可能小。更少的代码块花费更少的时间来执行,更少的时间让其他线程等待。

在这种情况下,您应该在 nodeList 级别进行同步。您可以使用包含节点列表的Collections.synchronizedList。它将为原子操作完成所有同步工作。但是,要将列表上的多个操作作为一个原子操作执行,您将需要显式同步。例如,当您读写时。查找代码示例here

【讨论】:

  • 是的,我试图澄清你向我解释的内容。太棒了!
【解决方案2】:

你可以做的是有一个线程安全的包装类,它可以访问进出ServetContext的节点列表对象

这个类可以使用一个

java.util.concurrent.locks.ReentrantReadWriteLock

只锁定节点列表的读写。

public class ThreadSafeAccessToNodeList
{
   private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

   private final Lock readLock = readWriteLock.readLock();
   private final Lock writeLock = readWriteLock.writeLock(); 

   public NodeList read (ServetContext sc)
   {
       readLock.lock();
       NodeList nl = null;
       try
       {
           // get the node list
           nl = (NodeList) sc.getAttribute("node_list");
       }
       finally
       {
            readLock.unlock();
       }
       return nl;
   }

   public void write (ServetContext sc, Object newData)
   {
       writeLock.lock();
       try
       {
           // get the node list
           NodeList nl = (NodeList) sc.getAttribute("node_list");

           // modify the node list with the new data
       }
       finally
       {
            writeLock.unlock();
       }    
   }
}

注意事项

  • 这样做的好处是不同步整个ServetContext
  • 此外,当需要更多 readLocks 时,此锁的性能最佳 与 writeLocks 相比。

【讨论】:

    猜你喜欢
    • 2012-01-20
    • 2023-03-04
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多