我有三个不同的类:
- 托管 bean(
单例
范围) - 托管 bean(
session
范围) - 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/