现在在做一个银行系统,想实现一张卡不能再两个地方同时取款的功能。想过用sychronized,但是那样效率太低,比方说我只是限制我这张卡不能同时消费,又没有限制其他的卡不能与我的卡同时消费,大家谁有这方面经验,,,
跪求

解决方案 »

  1.   

    恩,我知道概率太小,但是大家别忘了,这是银行啊,一点点错误都不能出现对吧?如果有点BUG被人利用了,我们的软件谁还敢用
      

  2.   

    呃,这倒是个问题。还能复制卡,高手啊?那只能记录一下登录的那台机器的类似电脑IP地址或者mvc地址了
      

  3.   

    用sychronized,但是那样效率太低
    有何证据 你的每秒交易量有多大  银行的服务器多的是
      

  4.   

    我想做的是让同一个账户不能同时操作。如果synchronized的话就是所有账户不能同时操作。
      

  5.   


    数据库里可以行锁
    此外就算代码里用synchronized也不等于影响所有用户,关键是锁什么。要是锁类当然影响所有用户,但锁加在哪个上面完全是可以自由控制的。
      

  6.   

    那既然是这种需要,那肯定是用synchronized啊首先你的“卡” ,他肯定是一个类对吧:假设为Card你在Card里面加个消费的方法,用synchronized比如
     
       public void synchronized  payFor(BigDecimal  moneyCount){
             ....业务操作
      }现在假设你有两张卡:c1,c2
      现在你在某个线程中用c1.payFor(xxxxxx);的时候,在其它线程中c1.payFor(xxxxx);就是被同步的,他是不能执行的,处于阻塞状态。但是你的c2.payFor();是不受影响的,明白??   public void synchronized  payFor(BigDecimal  moneyCount){
             ....业务操作
      }
    等同于
       public void payFor(BigDecimal  moneyCount){
                     synchronized  (this){                             ....业务操作
                 }
           
      }  只同步当前对象,明白?那如何保证卡是同一对象? 那就你重写equals () hashCode()   
      

  7.   

    恩,您的意思是说这样做么?if 两个线程对应的卡号相同  那么  同步else 正常刷卡
      

  8.   

    楼上正解,synchronized  java api本身都用了很多,这点效率其实一点都不影响,你说得同时刷卡,简单点就是数据库中加个字段,在刷之前先判断这个字段是1还是0,如果是1就是有人已经在使用其他不能用
      

  9.   


    synchronized只同步当前对象是什么意思??
      

  10.   

    synchronized(正在使用的卡对象) {
       //取钱
    }
      

  11.   


    首先,你的卡这个类public class Card{
      private String cardNo;//卡号
       private double balance;//余额,其它属性就不写了
       public void synchronized payment(double payMoney){
          //此处完成你的消费逻辑
      }
      
      //重写equals()和hashCode()方法, 根据卡号,也就是cardNo来判断唯一性
    }  public class TestCard{
             
            public static void main(String[] args){
                  Card c1 = new Card();
                  Card c2 = new Card();
                 
                   //这样就可以了,现在c1,c2调用payment()方法时都是同步的,怎么理解列?
                // 就是说如果有一个线程在调用c1.payment()方法的时候,其它线程是不能调用c1.payment(),因为
            //此时已经被同步,但是可以调用c2.payment();   因为payment()方法的synchronized同步的是在方法
          //范围内方法当前的调用对象。明白??
           }
       
       }
      

  12.   


         public void synchronized payment(double payMoney){
          //此处完成你的消费逻辑
      } //等同于
     public void payment(double payMoney){
               synchronized (this){                //此处完成你的消费逻辑
            }
      }
    如果你对这句话还不能理解,那我真的无能为力了。
      

  13.   

    锁加在哪里是跟你的设计架构相关的。假定把锁加在某个对象实例上,如:
    synchronized(o) { //o为对象实例
      //判断余额
      //减少余额
    }
    public synchronized method()这样的写法其实等价于synchronized(this)根据你的需求
    1)对于不同的卡,这个对象实例必须是不同的,否则就会影响别的卡的使用。
    2) 对于相同的卡,这个对象实例必须是相同的,否则就起不到互斥的作用。你首先检查自己的设计架构,是否已经存在符合这样特征的对象,若有,它就是个很好的加锁对象。若无,你可以创造出符合这样特征的对象,比如用HashMap建一个锁池。理解了这些,你就应该能明白,21楼所介绍的方法,其前提是payFor()方法所属的对象必须符合上述2个要求
      

  14.   

    看来看去,现在Java版,就那么几个人
      

  15.   

    如果采用synchronized(card)的方式,要做到c1,c2也能互斥,那么要保证底层的返回的bean是同一个才行,至于LS说的重写equals和hashCode是否真能保证c1,c2互斥,没试过我不太肯定,因为就算你重写了哪来两个方法,也不等使得c1==c2,也就是说还是两个对象,所以有点怀疑,所以如果采用这样的方法,那么在底层检索卡的时候,根据卡号返回同一个bean会比较好。
      

  16.   

    所以这里又返回到我刚才说的刷卡信息处理的问题,也就是第一个条刷卡信息来的时候,检索一个卡的bean放在缓存里,第二个刷卡信息来的时候,先在缓存里查找,如果存在则直接使用,如果不存在再从数据库检索,这样应该能做到返回同一个bean,而缓存的信息,可以设置一个timeout,到一定时间没有使用卡就从缓存清空
      

  17.   


    恩。这个考虑是有这个问题。  就算重写了equals方法,能不能保证拿个相同卡号的Bean,在调用同一个方法是同步的列? 虽然他们的内存地址是同一块....这个需要测试
      

  18.   

    线程。。同步
    我来做的话确实会这样考虑,但是实际代码还是需要不断run   debug  review run
    while(!noException){
             run   
             debug
             review
    }
    大大们看到不要鄙视
      

  19.   

    纯属是很基本的数据操作互斥问题. 如果是单一的数据库操作,就可以靠数据库的锁,否则可以在DAO层或上层加同步操作即可,另外,在这个问题上滥用缓存是危险的。
      

  20.   

    你这个同步根本不是一个synchronized的问题,事实上你可能处理这两笔同时业务的后台服务器根本不是同一个虚拟机,可能是在2台不同电脑上的。
      

  21.   

    恩,谢谢各位,其实我思考这个问题的方向已经错了。直接用hibernate 自带的乐观锁就可以解决一切
      

  22.   


    这个明显解决不了楼主问题吧 ? 在C1 C2 两个对象上分别同步 ,只是对象上所有标记synchronized的方法同步,c1c2 并没什么关系吧 ? 
      

  23.   

    如果每张卡是一个对象,刷卡是这个对象的方法,那么在这个方法上用sychronized,那么同步只是对这张卡同步,对其他卡没有影响