首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StampedLock的种族状况?

StampedLock的种族状况?
EN

Stack Overflow用户
提问于 2018-09-05 14:05:50
回答 2查看 151关注 0票数 0

我正在尝试为Hibernate实现我自己的序列生成器。开箱即用的是同步方法,这会导致我的应用程序中过多的争用(多线程将数据并行插入到Oracle数据库中)。

我正在考虑尝试一下StampedLock,但不幸的是,我的测试用例(有16个线程的150.000行)总是在150.000次执行中产生5-15个id冲突。

附加我的代码,你知道我做错了什么吗?或者你可以建议一个更好的方法吗?谢谢。

代码语言:javascript
复制
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.StampedLock;

import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IntegralDataTypeHolder;
import org.hibernate.id.SequenceGenerator;

public class HighConcurrencySequenceGenerator extends SequenceGenerator
{
  private StampedLock            lock   = new StampedLock();

  private AtomicLong             sequenceValue;   // the current generator value
  private IntegralDataTypeHolder lastSourceValue; // last value read from db
  private IntegralDataTypeHolder upperLimitValue; // the value to query the db again

  @Override
  public Serializable generate( SessionImplementor session, Object object )
  {
    long stamp = this.lock.readLock();
    try
    {
      while ( needsSequenceUpdate() )
      {
        long ws = this.lock.tryConvertToWriteLock( stamp );
        if ( ws != 0L )
        {
          stamp = ws;
          return fetchAndGetNextSequenceValue( session );
        }
        this.lock.unlockRead( stamp );
        stamp = this.lock.writeLock();
      }
      return getNextSequenceValue();
    }
    finally
    {
      this.lock.unlock( stamp );
    }
  }

  private long fetchAndGetNextSequenceValue( SessionImplementor session )
  {
    this.lastSourceValue = generateHolder( session );
    long lastSourceValue = this.lastSourceValue.makeValue()
                                               .longValue();
    this.sequenceValue = new AtomicLong( lastSourceValue );

    long nextVal = getNextSequenceValue();

    this.upperLimitValue = this.lastSourceValue.copy()
                                               .add( this.incrementSize );
    return nextVal;
  }

  private long getNextSequenceValue()
  {
    long nextVal = this.sequenceValue.getAndIncrement();
    return nextVal;
  }

  private boolean needsSequenceUpdate()
  {
    return ( this.sequenceValue == null ) || !this.upperLimitValue.gt( this.sequenceValue.get() );
  }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-07 05:02:04

我把IntegralDataTypeHolder upperLimitValue换成了AtomicLong,解决了这个问题。

票数 0
EN

Stack Overflow用户

发布于 2018-09-05 14:14:23

这段代码不是线程安全的。

代码语言:javascript
复制
this.sequenceValue = new AtomicLong( lastSourceValue );

在最坏的情况下,您将得到N个具有相同值的AtomicLong实例,其中N是正在运行的线程数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52187128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档