ThreadLocal种族条件与

我的比赛条件有点问题。

public class MyClass1 {
    static ThreadLocal<MyInterface> threads = new ThreadLocal();

    static MyInterface getThread(){
       return threads.get();
    }    

    static String saveId(String name){
       return getThread.saveId());
    }    
}

public interface MyInterface {
     String saveId(String name);
}

public class MyClass2 implements MyInterface {

    MyDao dao;

    public String saveId(String name){

    Session s= dao.getcurrentSession();
    String id =  (String)s.save(new myobject(name));
    return id;

   }

}

还有我的问题,当我尝试使用单例和休眠模式将对象保存到数据库时,如何排除竞争条件是更好的选择?

我认为,正确的解决方案是

private volatile String id;

public synchronized String saveId(String name){

        Session s= dao.getcurrentSession();
        id =  (String)s.save(new myobject(name));
        return id;   
   }

我错了吗?

P.S。 关于代码的第二个猜测:

    public String saveId(String name){

    Session s= dao.getcurrentSession();
    String id = s.createQuery("select id from myobject where name= :name order by id desc").setParameter("name",name).uniqueResult();

    if (!StringUtils.isEmpty(id)) {
     id = makeId(name);
    }

    return id; 
   }

 public String makeId(String name) {

   String id = s.createQuery("select id from myobject where name= :name order by id desc").setParameter("name",name).uniqueResult();

        if (!StringUtils.isEmpty(id)) {

            synchronized (MyClass2.class){
            id =  (String)s.save(new myobject(name));
            s.flush();
            }
        } 
     return id;
}
wyuan123 回答:ThreadLocal种族条件与

使用ThreadLocalsyncronized将无助于创建100%可靠的解决方案。只有3种可靠的方式完成此操作

  1. 对数据库具有唯一约束,并在错误时读取ID
  2. 执行UPSERT而不是INSERT(在INSERT失败时基本上执行UPDATE)并返回ID。要求对ID进行其他选择。
  3. 使用WHERE子句执行INSERT以防止名称的INSERT已经存在。要求对ID进行其他选择。

第二个和第三个仅适用于普通SQL查询。第二个取决于对数据库的支持。第一个选项应始终有效。

对数据库的唯一约束

  1. 更改表ALTER TABLE MyObject ADD CONSTRAINT UQ_MYOBJECT_NAME UNIQUE(name);
  2. 然后,您的方法应该执行save并从db读取错误。

    public String saveId(String name){
      Session s= dao.getCurrentSession();
      try {
        return (String) s.save(new MyObject(name));
      } catch (PersistenceException pe) {
        return s.createQuery("SELECT x FROM MyObject X where x.name=:name").setParameter("name",name).getSingleResult().getId(); 
      }
    }
    
  3. 您不需要ThreadLocal的东西,因为saveId方法中的线程之间没有共享,并且您可以安全地在线程之间重用单个实例(每个实例都有自己的{ {1}}等。

本文链接:https://www.f2er.com/3161614.html

大家都在问