论坛首页 Java企业应用论坛

web不同context中数据并发访问的疑问?

浏览 4080 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-07-24  
session context、application context这两种context中可以通过get、set attribute来存放各类数据,在web应用环境下肯定存在并发访问的问题,例如:为避免频繁查询数据库影响效率,在application context中存放一个attribute,为List实例,用来存放热销商品的清单,随商品访问量变化清单时刻在变化,对这个Map实例的操作就会是一个并发访问,必然存在并发控制的问题。

我的疑问:在常用的server中,如tomcat,此类并发问题是由server来控制,还是必须自己编程控制?若编程控制,如何控制?如何同步数据库与内存中数据?再进一步,若类似JNDI之类的目录库中存在这样的数据实体,其并发访问控制又是如何?

欢迎探讨!
   发表时间:2006-07-24  
好问题!

记得查过session和request的线程安全问题,好像是要自己控制的。不过不知道怎样才能有效控制。synchronized(session)这种东西理论上不保证正确,因为难说servlet容器永远给你传递同一个session/request对象。它要一高兴给你一个decorator,就歇了。

xfire里面为了保险,用了synchronized(HttpSession.class)这个影响并发性的方法。

application我想应该是线程安全的。
0 请登录后投票
   发表时间:2006-07-24  
一个细粒度的并发控制方法是:悲观锁加在session id 上。

引用

try{

  // lock 可以做成是同步的,获取锁之前不返回 (wait, notify)
  // 也可以是异步的。
  if( sessionLocks.lock(sessionId) ) {
     // operate session, get , set attribute
  }else{
     // locked by others, give up or wait
  }

}finally{
   // 释放sessionId对应的Lock,通知其他等候操作该session的thread
   sessionLocks.unlock(sessionId);
}



sessionLocks内部可以用Synchronized Map (also, wait, notify, etc)来实现。

这种机制可以通用于一个JVM的一个Application内的细粒度并发控制。锁的粒度可以根据需要自定义。
0 请登录后投票
   发表时间:2006-07-24  
有点复杂.
那么request呢?有request id这个东西么?

还有,这个map怎么保证垃圾收集呢?假设某个session对象已经expire了,这个id是不是能自动从map中清掉呢?
0 请登录后投票
   发表时间:2006-07-24  
ajoo 写道
有点复杂.
那么request呢?有request id这个东西么?

还有,这个map怎么保证垃圾收集呢?假设某个session对象已经expire了,这个id是不是能自动从map中清掉呢?


request应该是一个thread一个吧。

id的清除是依靠那个 try { } finally {} 的finally里面的 sessionLocks.unlock保证的。如果finally之前陷入了死循环,确实就没有办法清除了。
过期session id的清除,一般用不着。如果出现了上述的情况,也可以通过listen session的事件来得知过期事件 session evicted out event。
0 请登录后投票
   发表时间:2006-07-24  
再加上listener就更复杂了一点。不过大概也只有这样了吧?

不过,每个servlet的使用者怎么拿到这个locks对象呢?ioc?还是service locator?
0 请登录后投票
   发表时间:2006-07-24  
ajoo 写道
再加上listener就更复杂了一点。不过大概也只有这样了吧?

不过,每个servlet的使用者怎么拿到这个locks对象呢?ioc?还是service locator?


singleton 全局变量应该是最简单的方法。
serviceLocator也可以做成singleton.
ioc注入servlet还是比较难的。

(从一些资料里面看到,好像singleton 全局变量之类的,是很受抵制的反模式?)
0 请登录后投票
   发表时间:2006-07-24  
关于Request
Servlet Spec. 写道

Implementations of the request and response objects are not guaranteed to be thread
safe. This means that they should only be used within the scope of the request handling
thread.
References to the request and response objects should not be given to objects
executing in other threads as the resulting behavior may be nondeterministic. If
the thread created by the application uses the container-managed objects, such as
the request or response object, those objects must be accessed only within the
servlet’s service life cycle and such thread itself should have a life cycle within
the life cycle of the servlet’s service method because accessing those objects
after the service method ends may cause undeterministic problems. Be aware
that the request and response objects are not thread safe. If those objects were
accessed in the multiple threads, the access should be synchronized or be done
through the wrapper to add the thread safety, for instance, synchronizing the call
of the methods to access the request attribute, or using a local output stream for
the response object within a thread.


关于Session
Servlet Spec. 写道

Multiple servlets executing request threads may have active access to a single
session object at the same time. The Developer has the responsibility for
synchronizing access to session resources as appropriate.
0 请登录后投票
   发表时间:2006-07-24  
给出LockManager的大致实现。

import java.util.HashMap;
import java.util.Map;

public class LockManager {
	protected Map map = new HashMap();;

	public synchronized boolean lockNoWait(Object id);{
		Object lock = map.get(id);;
		if(lock != null);
			return false;
		
		map.put(id, new Object(););;
		return true;
	}

	protected synchronized Object getLock(Object id);{
		return map.get(id);;
	}
	
	public boolean lockWait(Object id, long timeout);{
		if(lockNoWait(id););{
			return true;
		}
		
		Object lock = getLock(id);;
		if(lock != null);try {
			lock.wait(timeout);;
		} catch (InterruptedException e); {
			e.printStackTrace();;
		}

		return lockNoWait(id);;
	}
	
	public boolean lockWaitAlways(Object id);{
		boolean b = lockNoWait(id);;
		
		while(!b);{
			Object lock = getLock(id);;
			if(lock != null);try {
				lock.wait();;
			} catch (InterruptedException e); {
				e.printStackTrace();;
			}
			b = lockNoWait(id);;
		}

		return true;
	}

	public synchronized void unlock(Object id);{
		Object lock = map.remove(id);;
		if(lock != null);
			lock.notifyAll();;
	}
}

0 请登录后投票
   发表时间:2006-07-25  
Readonly 写道
关于Request
Servlet Spec. 写道

Implementations of the request and response objects are not guaranteed to be thread
safe. This means that they should only be used within the scope of the request handling
thread.
References to the request and response objects should not be given to objects
executing in other threads as the resulting behavior may be nondeterministic. If
the thread created by the application uses the container-managed objects, such as
the request or response object, those objects must be accessed only within the
servlet’s service life cycle and such thread itself should have a life cycle within
the life cycle of the servlet’s service method because accessing those objects
after the service method ends may cause undeterministic problems. Be aware
that the request and response objects are not thread safe. If those objects were
accessed in the multiple threads, the access should be synchronized or be done
through the wrapper to add the thread safety, for instance, synchronizing the call
of the methods to access the request attribute, or using a local output stream for
the response object within a thread.


关于Session
Servlet Spec. 写道

Multiple servlets executing request threads may have active access to a single
session object at the same time. The Developer has the responsibility for
synchronizing access to session resources as appropriate.


如此看来,server无须负责session所载attribute的并发访问问题,attribute的并发访问完全可以从一个普通对象实体的并发访问来考虑,并无特殊性,且由应用开发者负责并发问题。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics