Java 使用同步线程的线程安全性
我正试图在我的JAX-RS项目中编写一些代码。由于这是与iBeacon相关的,我需要为给定的用户生成要存储的主次号 注册用户的代码如下:Java 使用同步线程的线程安全性,java,mysql,multithreading,concurrency,ibeacon,Java,Mysql,Multithreading,Concurrency,Ibeacon,我正试图在我的JAX-RS项目中编写一些代码。由于这是与iBeacon相关的,我需要为给定的用户生成要存储的主次号 注册用户的代码如下: /** * Register a user to the application. Registration requires unique * username and unique email address. * @Override * @param username the username to register with * @para
/**
* Register a user to the application. Registration requires unique
* username and unique email address.
* @Override
* @param username the username to register with
* @param password the password to register with
* @param email the email to register with
* @param firstname the users firstname
* @param lastname the users lastname
* @return RegistrationStatus to determine if the method succeeded or not
* @throws MajorMinorException
*/
public synchronized RegistrationStatus register(String username, String password,String email, String firstname, String lastname) throws MajorMinorException {
if(StringUtilities.stringEmptyOrNull(username, password, email, firstname, lastname)){
throw new IllegalArgumentException ("Unable to register the user as a value which is needed is null or empty");
}
if(!StringUtilities.validEmail(email)){
throw new IllegalArgumentException("The email is not in a valid format to register with");
}
if(!StringUtilities.validPassword(password)){
throw new IllegalArgumentException("The password " + password + " for user " + username + " was not in a valid format");
}
RegistrationStatus result = RegistrationStatus.FAILED;
try {
int major = super.getMajorMinor(true, username, source.getConnection());
int minor = super.getMajorMinor(false, username, source.getConnection());
if(major == -1 || minor == -1){
throw new MajorMinorException("Major/Minor value was -1, possible bad data: " + username + " " + email);
}
Tuple<Integer, Integer> majorMinorPairs = IBeacon.incrementMajor(major, minor);
result = register(username, password, email, firstname, lastname, majorMinorPairs.getFirst(), majorMinorPairs.getSecond(), source.getConnection());
logger.info("major minor generated for user " + username + " major: " + majorMinorPairs.getFirst() + " minor: " + majorMinorPairs.getSecond());
} catch (SQLException e) {
logger.error("An error occured when registering", e);
return result;
}
return result;
}
/**
*向应用程序注册用户。注册要求唯一性
*用户名和唯一的电子邮件地址。
*@覆盖
*@param username要注册的用户名
*@param password要注册的密码
*@param通过电子邮件发送要注册的电子邮件
*@param firstname用户的firstname
*@param lastname用户的lastname
*@return RegistrationStatus以确定方法是否成功
*@majorminoexception
*/
公共同步注册状态寄存器(字符串用户名、字符串密码、字符串电子邮件、字符串名字、字符串姓氏)引发MajorMinorException{
if(StringUtilities.stringEmptyOrNull(用户名、密码、电子邮件、名字、姓氏)){
抛出新的IllegalArgumentException(“无法将用户注册为需要的值,该值为null或空”);
}
如果(!StringUtilities.validEmail(电子邮件)){
抛出新的IllegalArgumentException(“电子邮件的注册格式无效”);
}
如果(!StringUtilities.validPassword(密码)){
抛出新的IllegalArgumentException(“用户“+username+”的密码“+password+”格式无效”);
}
RegistrationStatus结果=RegistrationStatus.FAILED;
试一试{
int major=super.getMajorMinor(true,用户名,source.getConnection());
int minor=super.getMajorMinor(false,username,source.getConnection());
如果(大调==-1 | |小调==-1){
抛出新的MajorMinorException(“主/次值为-1,可能是坏数据:“+username+”+“+email”);
}
元组majorMinorPairs=IBeacon.incrementMajor(major,minor);
结果=注册(用户名、密码、电子邮件、firstname、lastname、majorMinorPairs.getFirst()、majorMinorPairs.getSecond()、source.getConnection());
logger.info(“为用户“+username+”major:+majorMinorPairs.getFirst()+”minor:+majorMinorPairs.getSecond()生成的主次命令”);
}捕获(SQLE异常){
logger.error(“注册时发生错误”,e);
返回结果;
}
返回结果;
}
现在我可以预见一个潜在的场景,我们可能会遇到问题。原因是super.getMajorMinor(true,username,source.getConnection())代码>对数据库表执行MAX,然后将其递增1。因此,我假设有可能同时出现2条max语句(在用户注册该语句对之前),因此我们将得到脏读/写
我可以锁定表以保持数据的完整性,但另一个解决方案是同步寄存器方法。我相信这将产生与锁定表相同的效果,但性能影响会更糟吗
谢谢,因为您的方法是同步的
,寄存器中只能有一个线程(每个实例)。但是,如果你怀疑还有其他无关的操作可以修改你所说的列,那么你应该考虑让数据库来做这项工作。您知道,使用声明为unique、auto increment等的列。不幸的是,我不确定这是否可行,因为iBeacon在包装之前的有效数字范围高达65536。我认为人工智能不够灵活,尽管我可能错了