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
###### 请参考: 线程安全的判定