首页 \ 问答 \ 如何在字符串的情况下使用同步?(How should the synchronization be used in case of strings?)

如何在字符串的情况下使用同步?(How should the synchronization be used in case of strings?)

我在DB中有一个学生表,其中包含名称,主题和标记字段。 1名学生可以在此表中为不同科目创建多个记录。

我有一个学生DAO类,它有一个像这样的更新方法:

public marks updateStudent(String name, String subject, int marks){
//this method first check if the record of this name and subject is there in DB
    if(getStudentRecordFromDB(name, subject){
        //then return marks for this student

    }else{
        //insert the record in DB and return marks
        insertRecord(name, subject, marks);

    }

}

对于同一学生姓名和科目,可以同时为多个线程调用此方法。 我想只在多个线程更新相同名称和主题的情况下使其同步。 所以我想在名字+主题的字符串上同步这个方法但是因为这是一个不好的做法也没有给我保证结果由于字符串常量池(在其中存在该字符串),我想使用一些更好的解决方案。 我不想在DAO.class上进行同步,因为我只想在同一记录更新的情况下进行同步。 最好的方法是什么?


I have a student table in DB which has name, subject and marks fields in it. 1 student can have multiple records for different subjects in this table.

I have a student DAO class which has an update method like this:

public marks updateStudent(String name, String subject, int marks){
//this method first check if the record of this name and subject is there in DB
    if(getStudentRecordFromDB(name, subject){
        //then return marks for this student

    }else{
        //insert the record in DB and return marks
        insertRecord(name, subject, marks);

    }

}

This method can be called by multiple threads simultaneously for same student name and subject. I want to make it synchronized only in case of multiple threads updating same name and subject. So I thought on synchronizing this method on string of name+subject but as this is a bad practice also not giving me guranteed results due to string constant pool (presence of that string in it), I want to use some better solution. I don't want to synchronize on DAO.class as I want synchronization only in case of same records update. What should be the best way to do this?


原文:https://stackoverflow.com/questions/37560026
更新时间:2019-12-13 07:37

最满意答案

对于同一学生姓名和科目,可以同时为多个线程调用此方法。

一种方法是在数据库上创建一个唯一的限制,如果数据库已经有学生名/主题组合,则会引发异常。 所以你会:

  1. 查询学生姓名/科目
  2. 如果它不存在,请尝试将其插入数据库中
  3. 如果失败则再次执行查询以防止竞争条件。
  4. 如果它仍然不存在则抛出数据库异常

可以使用同步执行此操作,尽管这不是一件容易的事。 你可以这样做:

  1. 创建一个包装学生名/主题的对象,其中hashcode()equals()使用这些字段。
  2. 每当你去做你的操作时,使用ConcurrentHashMapputIfAbsent(...)你的StudentNameSubject 。 该值可以只是一些随机常量对象,因为您不能使用null并且没有ConcurrentHashSet
  3. 然后在您创建的StudentNameSubject或地图中的StudentNameSubject上同步(如果已存在)。
  4. synchronized块中执行数据库操作。
  5. 完成synchronized块后,可以从地图中删除该条目。

This method can be called by multiple threads simultaneously for same student name and subject.

One way to do this would be to create a unique restriction on your database that will throw an exception if the database already has the student-name/subject combination. So you would:

  1. query for the student-name/subject
  2. if it didn't exist, try to insert it in the database
  3. if that fails then do the query again to protect against the race condition.
  4. if it still doesn't exist then throw the database exception

You could do this with synchronization although it is non trivial. You could do something like:

  1. Create a object that wraps the student-name/subject where the hashcode() and equals() use those fields.
  2. Use a ConcurrentHashMap and putIfAbsent(...) your StudentNameSubject whenever you go to do your operation. The value can just be some random constant object since you can't use null and there is no ConcurrentHashSet.
  3. Synchronize then on either the StudentNameSubject you created or the one from the map if it already exists.
  4. Do your database operations inside the synchronized block.
  5. You can delete the entry from the map after you complete the synchronized block.
2016-06-09

相关文章

更多

最新问答

更多
  • 这个listArray是如何填充的?(How is this listArray populated?)
  • iOS 7上的CTSubscriber(以及如何使用它)是什么?(What's CTSubscriber (and how to use it) on iOS 7?)
  • 手动创建VisualStudio 2012项目文件(Manually creating VisualStudio 2012 project file)
  • 删除不适用于JSP中使用for循环的每个id(Deletion not working for every id using for loop in JSP)
  • 如何从std :: filesystem :: path中删除引号(How to remove quotation marks from std::filesystem::path)
  • 验证多个控制器方法的URL路径(Validate URL path for several controller methods)
  • 如何在datarow []中的列中找到最大值?(How to find max value in a column in a datarow[] ?)
  • 如何使用预定义文本替换来自数据库的部分结果(How do I replace part of result coming from Database with predefined text)
  • Selenium Java注入了新的Javascript函数(Selenium Java inject new Javascript function)
  • 使用.on的多个下拉菜单选择文本仅适用于第一个下拉列表(Multiple Dropdowns Menu Selection text using .on works only on first dropdown)
  • 快速将黄土曲线添加到大型数据集图中的方法(Quick way to add loess curve to large data set graph)
  • FilteringSelect in mvc(FilteringSelect in mvc)
  • 在Delphi XE2中开发Mac或iOS应用程序需要哪些硬件/软件?(What hardware/software is necessary to develop Mac or iOS apps in Delphi XE2?)
  • 在原型的构造函数中初始化属性时获取“未定义”(Getting 'undefined' when a property is initialized in the constructor of a prototype)
  • 通过越狱加载的应用程序的Documents文件夹位置(Location of Documents folder for an app loaded via jailbreak)
  • 在OpenGL中使用可编程和固定管道功能(Using both programmable and fixed pipeline functionality in OpenGL)
  • 将任何用户输入重定向到单独的底层程序(redirect any user input to a separate underlying program)
  • 编辑文本不能正常工作android(Edit texts not working properly android)
  • “user_denied”Facebook应用页面上的Facebook用户区域设置(Facebook user locale on “user_denied” facebook app page)
  • 在大图像中找到小的部分透明图像的坐标(find coordinates of small partially-transparent image within a large image)
  • 我如何在cakephp 3.1中获得完整的相对路径?(How i can get full relative path of image in cakephp 3.1?)
  • 如何保存拖动标记的新本地化?(How to save new localization of dragged marker?)
  • MySQL UPDATE vs INSERT和DELETE(MySQL UPDATE vs INSERT and DELETE)
  • 在执行查询之前,在SQLAlchemy模型中将datetime转换为unix时间戳?(Convert datetime to unix timestamp in SQLAlchemy model before executing query?)
  • OpenCL与OpenGL互操作的优势(Advantage of OpenCL interoperability with OpenGL)
  • 如何解析用点和等分隔的数据然后添加到listview(How to parsing data from delimited with dot and equal then add to listview)
  • 带调试输出的X3解析器段错误(BOOST_SPIRIT_X3_DEBUG)(X3 parser segfaults with debug output (BOOST_SPIRIT_X3_DEBUG))
  • 将文件夹名称添加到fgrep结果(Add folder name to fgrep result)
  • 在MySQL中加载一个表是非常慢的(Loading one table in MySQL is ridiculously slow)
  • 如何将JSON放入PHP变量?(How do I put JSON into a PHP Variable?)