java - 应该同步哪些代码块?

标签 java spring synchronization synchronized managed-bean

我有三个不同的类:

  1. 托管 bean(单例 范围)
  2. 托管 bean( session 范围)
  3. Spring @Controller

我在这里读了一些关于同步的文章,但我仍然不明白它应该是怎样的以及它是如何工作的。

简短示例:
1) 托管 bean(单例 范围)。
这里所有用户的所有类字段都应该相同。所有用户都使用该对象的一个​​实例或其副本(???)。

    public class CategoryService implements Serializable {
private CategoryDao categoryDao;
private TreeNode root; //should be the same for all users
private List<String> categories = new ArrayList<String>();//should be the same for all users
private List<CategoryEntity> mainCategories = new ArrayList<CategoryEntity>();
//should be the same for all users

public void initCategories() {
    //get categories from database
}

public List<CategoryEntity> getMainCategories() {
    return mainCategories;
}}  

2) 托管 bean(session 作用域)
在这种情况下,每个用户都有自己的对象实例。
当用户试图删除类别时,他应该检查是否有其他用户试图删除相同的类别,所以我们需要使用 synchronized block ???

public class CategoryServiceSession implements Serializable {
private CategoryDao categoryDao;
private CategoryService categoryService;

private TreeNode selectedNode;

public TreeNode getSelectedNode() {
    return selectedNode;
}
public void setSelectedNode(TreeNode selectedNode) {
    this.selectedNode = selectedNode;
}

public void deleteCategory() {
    CategoryEntity current = (CategoryEntity) selectedNode.getData();

    synchronized (this) {
        //configure tree
        selectedNode = null;
        categoryDao.delete(current);
    }
    categoryService.initCategories();
}}  

3) Spring @Controller
这里所有用户都可能有一个实例(或者每个用户都有自己的实例???)。但是当一些管理员试图改变一些用户的参数时,他应该检查是否有另一个管理员试图做同样的操作??

@Controller
@RequestMapping("/rest")
public class UserResource {
   @Autowired
   private UserDao userDao;

   @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
    public @ResponseBody UserEntity changeBannedStatus(@PathVariable Long id) {
        UserEntity user = userDao.findById(id);
        synchronized (id) {
           user.setBanned(!user.getBanned());
           userDao.update(user);
        }
    return user;
    }
}

那么,它应该如何呢?

对不起我的英语。

最佳答案

在您发布的代码中——没有什么特别需要同步的,您定义的同步块(synchronized block)不会保护您免受任何影响。默认情况下,您的 Controller 范围是单例。

如果您的单例更改了共享对象(主要只是它们的字段),那么您应该将整个方法标记为已同步。

方法级变量和最终参数可能永远不需要同步(至少在您似乎正在使用的编程模型中是这样)所以不用担心。

session 对象主要由序列化保护,但如果您的用户有并发请求,您仍然可能会发生数据竞争——您必须想出创造性的方法来处理这个问题。

您可能/将在数据库中遇到并发问题(多个用户试图同时删除或修改数据库行)但这应该通过 DAO 中的悲观或乐观锁定和事务策略来处理。

运气。

关于java - 应该同步哪些代码块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31341032/

相关文章:

java - 简单的框架跳过 SOAP 信封和 body

java - 获取流中符合条件的第一个元素

java - @RequestParam 和 @PathVariable

java - Java Spring @Autowired无法按预期工作

spring - 由于删除了 JobDetailAwareTrigger,升级到 Spring 4.1 会破坏 Quartz Persistence

database - 关系数据库是并行执行插入语句还是顺序执行?

javascript - 如何将 Json 数组传递给 IN 运算符的 JPQLWhere 子句?

java - 如何用spring在redis的缓存中创建文件夹?

java - java中两个线程同时访问一个变量

sql-server - 如何使两个相关但独立的系统保持同步?