关于多线程下Synchronized锁和ReentrantLock的问题

  1. 现在有如下的业务场景:
    数据库里边只有id,time2个字段,数据库里边id是自增的。现在需要对id进行一次更新之后,再去进行查询,
    以期获得最新的id,并返回给业务方。
    public IDGenerateEntityDb execSql(final String time) throws Exception {
    DaoWrapper wrapper = BaseDaoWrapperFactory.getDaoWrapper();
    final String sql = "replace into tbl (time) values(" + time + ")";
    IDGenerateEntityDb db = new IDGenerateEntityDb();
    final Lock lock = new ReentrantLock();
    lock.lock();
    Long id = (Long) wrapper.execInsert(sql, new IPreparedStatementHandler() {
    public Object exec(PreparedStatement paramPreparedStatement) throws SQLException {
    int s = paramPreparedStatement.executeUpdate(sql);// 返回的是执行的条数
    Long idLong = null;
    try {
    if (s == 1 || s == 2) { // 表明执行成功
    ResultSet set = paramPreparedStatement.executeQuery(" SELECT * from tbl where time= " + time);
    while (set.next()) {
    idLong = set.getLong("id");
    System.out.println(idLong);
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    lock.unlock();
    }
    return idLong;
    }
    });
    db.setId(id);
    return db;
    }

    用这种方式的时候,拿到的结果就会有重复数据,但是将ReentrantLock改为Synchronized后拿到的结果就正常了,这是什么原因呢。是不是加锁的额方式不对呢?
    

finally代码块中执行lock.unlock(),此时释放了锁,但在释放锁之前,已经有返回值了。你将return idLong;放到lock.unlock();之后就可以了。

上述代码,也不可以。如果插入语句之后,关闭连接,然后再执行是可以的。相信说到这里,你已经知道为什么了。。。