论坛首页 Java版 Hibernate

提问:关于线程安全性的问题

浏览 3113 次
该帖已经被评为精华帖
作者 正文
时间:2004-01-17
举个例子:
一个教师类中包含了多个学生,如果该教师类已经被cache缓存了,
那么如果有两个操作正在同时进行,一个操作在遍历该教师的学生,
而另一个操作在删除该教师的某个学生,
那么,是否会有线程不安全的问题呢?
   
时间:2004-01-17
不知我的意思表达清楚了没有,我是在看
http://www-900.ibm.com/developerWorks/cn/java/j-jtp09263/index.shtml
这篇文章的时候忽然想到的,因为hibernate底层提供了cache机制,那么在多线程环境下,就有可能有多个人同时拿到了教师类的同一个实例,那么如果有人在删除一个学生,而另一个人在遍历学生时,就很可能会出问题,不知hibernate是如何解决的?
   
0 请登录后投票
时间:2004-01-18
Hibnerate uses lock and version for this:
see

net.sf.hibernate.cache.ReadWriteCache

[code:1]
/**
* Do not return an item whose timestamp is later than the current
* transaction timestamp. (Otherwise we might compromise repeatable
* read unnecessarily.) Do not return an item which is soft-locked.
* Always go straight to the database instead.<br>
* <br>
* Note that since reading an item from that cache does not actually
* go to the database, it is possible to see a kind of phantom read
* due to the underlying row being updated after we have read it
* from the cache. This would not be possible in a lock-based
* implementation of repeatable read isolation. It is also possible
* to overwrite changes made and committed by another transaction
* after the current transaction read the item from the cache. This
* problem would be caught by the update-time version-checking, if
* the data is versioned or timestamped.
*/
public synchronized Object get(Object key, long txTimestamp) throws CacheException {

if ( log.isTraceEnabled() ) log.trace("Cache lookup: " + key);

try {
cache.lock(key);

Lockable lockable = (Lockable) cache.get(key);

boolean gettable = lockable!=null && lockable.isGettable(txTimestamp);

if (gettable) {
if ( log.isTraceEnabled() ) log.trace("Cache hit: " + key);
return ( (Item) lockable ).getValue();
}
else {
if ( log.isTraceEnabled() ) {
if (lockable==null) {
log.trace("Cache miss: " + key);
}
else {
log.trace("Cached item was locked: " + key);
}
}
return null;
}
}
finally {
cache.unlock(key);
}
}

and

/**
* Do not add an item to the cache unless the current transaction
* timestamp is later than the timestamp at which the item was
* invalidated. (Otherwise, a stale item might be re-added if the
* database is operating in repeatable read isolation mode.)
*/
public synchronized boolean put(Object key, Object value, long txTimestamp) throws CacheException {
if ( log.isTraceEnabled() ) log.trace("Caching: " + key);

try {
cache.lock(key);

Lockable lockable = (Lockable) cache.get(key);

boolean puttable = lockable==null || lockable.isPuttable(txTimestamp);

if (puttable) {
cache.put( key, new Item( value, cache.nextTimestamp() ) );
if ( log.isTraceEnabled() ) log.trace("Cached: " + key);
return true;
}
else {
if ( log.isTraceEnabled() ) {
if ( lockable.isLock() ) {
log.trace("Item was locked: " + key);
}
else {
log.trace("Item was already cached: " + key);
}
}
return false;
}
}
finally {
cache.unlock(key);
}
}

[/code:1]
   
0 请登录后投票
时间:2004-01-18
从这些代码来看,好象在get和put时,都是需要同步的,这样的话,在大量的并发请求的处理上,不知会不会对性能有所影响?

而且,我前面疑惑的问题的关键并不是在get方法的同步问题上,
我的疑惑是:如果有两个并发用户都通过cache拿到了教师的同一个实例,那么如果有一个用户在遍历该教师的所有学生,而另一个用户正巧删除了某个学生,这样是否会产生并发问题?
因为通过Iterator进行遍历时,该遍历器是不允许被删除或新增元素的
   
0 请登录后投票
论坛首页 Java版 Hibernate

跳转论坛:
JavaEye推荐