以theadsafe方式

时间:2016-05-25 02:08:06

标签: java mysql multithreading java-ee concurrency

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

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

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

2 个答案:

答案 0 :(得分:1)

你可以做的是拥有一个类,它是一个线程安全的包装器,可以访问进出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相比。

答案 1 :(得分:1)

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

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