java线程安全的处理我知道的现在就2种
比如我有这样一个对象
public class User {
private int id;
private String name;
private int money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
public class UserDao {
public User getById(int id){
...
}
public User getByType(int type){
...
}
}
为何synchronized不起作用呢?下面代码解释
public class A_Thread implements Runnable{
public void run() {
//此时查询出来的数据是原数据的一个clone 原数据再怎么变这个对象也不会受影响
User user = UserDao.getById(1);
Thread.sleep(1000);
user.setMoney(user.getMoney()+10);
user.update();
}
}
public class B_Thread implements Runnable{
public void run() {
//此时查询出来的数据是原数据的一个clone 原数据再怎么变这个对象也不会受影响
User user = UserDao.getById(1);
Thread.sleep(1000);
user.setMoney(user.getMoney()+10);
user.update();
}
}
public class Test{
public static void main(String[] agrs){
ExecutorService exe = Executors.newFixedThreadPool(8);
exe.execute(new A_Thread());
exe.execute(new B_Thread());
}
}
public static void main(String[] agrs){
User user = UserDao.getById(1);
int money = user.getMoney();
money = ???
}
结果这个user的 值根本确定不了 无论在那加 synchronized
public synchronized int getMoney() {
return money;
}
public synchronized void setMoney(int money) {
this.money = money;
}
到这大概有人会说把User保留一分在内存中,查询始终,修改始终都是操作的内存中这个User对象!
但会有以下几个问题
1.数据会出出现完整性问题(多线程并发的时候 你一个逻辑线程需要set 10属性,但才3个,另外一个逻辑线程要取这个对象,那个瞬间他取过去的数据实际上就只改了3个属性)
2.如果我set了 但是update失败!但是内存中的数据任然有部分已经受到了影响
好了!synchronized不能很好的解决我的问题,那么我就来用Lock。Lock必须显示的加锁和放锁
我要防止上面的问题,在比如getById()的时候就有了2中加锁方式,加读锁和写锁。我需要修改的查询就在调用getById中加上写锁,只读不修改的时候就加读锁。而现在问题又来了
并且我是加在User的实例对象上的,加载Dao也可以但性能会底很多!
1.我加了写锁之后必须等我逻辑线程处理完后 简单的说就是要 update之后才能放锁!
2.如果逻辑线程在取得写锁后逻辑出现异常了!导致没有换锁!
解决这个我的处理试了一下几种
1.加了个最大持有该锁的时间,当另外一个线程要获得该锁的时候检查时间,如果超过时间,中断持有改锁的线程(不大友好)
2.定时检查,但并发高的时候会有很多定时器
3.改造getById(int id)方法,getById(int id,List<Lock> locks) 在查询中传一个List进去,把该次操作的的Lock反馈出来,在逻辑处理完后全部释放!
List<Lock> locks = new ArrayList();
try {
//业务逻辑
getById(1,locks);
} catch (Exception e) {
}finally{
//locks 全部释放掉
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
我做的是不是一个功能,而是想封装一个框架,最大的简化逻辑层的代码!######回复 @sxgkwei : 我只能 呵呵。。。######逻辑层的代码?这个都能简化?既然叫做逻辑层,那就说明是跟着具体业务逻辑走的。这个完全没有可简化空间吧?######事务?######没人?######根本没有耐心看完######不知道我说的对不对,因为我没看完你贴的代码,感觉你把问题想复杂了。我感觉在dao这块,不必使用线程安全吧,数据库的锁机制应该满足要求了吧,大不了搞搞约束和事务处理,个人感觉实在没必要控制线程,容易出现死锁甚至影响效率######回复 @SandKing : 进程级的内存?新名词?######我那个DAO只是一个简单的例子! 我要做的是进程级的内存!######楼主需要的是数据库的隔离级别######你的synchronized 锁的是对象,但是你两个线程分别返回了不同的对象,因此互不影响,所以你的synchronized当然没有效果了######用只是举例说明。。。######根本不是synchronized的问题,你这里是不是想做单例??通过单机的内存来管理JVM中只存在一个对象??######回复 @SandKing : 是啊,那你怎么还用######所以我才说,synchronized对于我的这个需求无用!######数据有共享才有线程安全性问题,文中提到的问题应该是数据库层面的问题。
1、同步 数据层的查询和更新方法。或者业务逻辑层的方法
2、sql语句,查询时+ for update
###### 请参考: 线程安全的判定