一个订票系统
每个客户端需要根据服务器端的数据来决定可以卖给用户几张票
现在假设A客户端查询了服务器,返回票数是10张
但同时,B客户端将其中的5张卖掉
因服务器无法通知A客户端B已经作了这个操作
这时A客户端看到的票还是10张
请问,如何处理这样的情况

解决方案 »

  1.   

    加锁~~~~~~~
    见意:先去看看《操作系统》中关于进程同步的问题,能后再来看看Java中的线程同步和Java是怎么结决的~~~
      

  2.   

    如果使用数据库,就直接用业务操作。
    没有数据库就加锁。
    --------
    >楼上,请问一下你打算怎么通知客户端服务器数据被另一个客户端修改了
    A执行卖操作的时候就知道了,不要通知
      

  3.   

    你说A执行卖操作的时候就知道了,不要通知问题是A他不执行卖操作,他只是看了一下还有多少张票,然后告诉客户我们现在有多少张票可以卖给你,等A他执行卖操作的时候,发现没有这么多票可卖,但已经来不及了
      

  4.   


    “请问一下你打算怎么通知客户端服务器数据被另一个客户端修改了”
      客户端所显示出来的数据是什么时候的? 是在等到有客户来买票的时候再去一下数据库中拿数据,还是老早数据库就把数据就给了客户端?
      这样类似的问题有很多,就不多做解释了,数据应当是客户买票时再去数据库去查询数据。
      做查询的时候无所谓,但是当有一个客户端要卖票,要对数据库做update了,这个时候就应当对update操作加锁。这样类似的问题也很多,不多解释了。
      后面的问题是,当一个客户端执行了update之后,其它的客户端所查询到的数据可能还保持在update之前~!  如果楼主你的问题是在这的话,我想我应当对你说声抱歉~!!!,把你当新手看待了~!!!  我临时想到的一个解决方案就是客户端每要执行update之前先去查一下数据库~~~
    这个办法会有一些问题,就是答应了用户的要求可然又满足不了用户的要求~~~
    其它更好的办法暂时还没有想到,等想到了再给你回贴~~~
      

  5.   

    做查询的时候无所谓,但是当有一个客户端要卖票,要对数据库做update了,这个时候就应当对update操作加锁。这样类似的问题也很多,不多解释了。
    ======================================================================
    你说的这个这个时候就应当对update操作加锁实际上是行不通的
    我举一个这样的例子
    比如,一棵树,多客户端可以更新
    现在,假设A客户端要在树上现有的一个节点a添加一个子节点的时候,这时他调用了一个查询问数据库节点a是不是还存在,如果存在,就按你说的,这个时候就应当对update操作加锁,问题是,在你提交加锁的这个过程中,a节点被另一个客户端删除了,请问,这种情况你怎么处理
      

  6.   

    你这个问题不是和我上面说的一样吗===============================================
     我临时想到的一个解决方案就是客户端每要执行update之前先去查一下数据库~~~
    这个办法会有一些问题,就是答应了用户的要求可然又满足不了用户的要求~~~
    其它更好的办法暂时还没有想到,等想到了再给你回贴~~~===============================================
      

  7.   


    二次更新
    我以前做过一个这样的例子,
    更新肯定是先查询的吧?,此时,table中有一个字段是updDate,记录下该最后更新时间,然后做更新时再次读取该时间,若不相等,则不更新;
    但是此方法不适用于频繁更新的系统;
      

  8.   

    刚想了一个办法,供你参考参考:预订~!!!
    就是服务器开始时就把票分配给所有的客户端。
    这样客户端开始时就得到了一批属于自己的票了,就相当于有了个自相互独立的“数据库”了,而服务器中的数据库这个临界点就不存在了。所以客户端在卖票的时候也不用再对服务器上的数据库再做查询和更新了,只要对自己本地上老早由服器发来的数据进行查询和更新就可以了。
    但是会有这样一个问题:就是有的客户端卖票卖得很好,有的客户端不景气。
    所以就应当设置:当客户端的票不足的时候,再向服务器申请,而不能直接去访问服务器上的数据库,服务器得到了申请,再查看一下各个客户端的卖票情况,由服务器来统一调配。
     这时又会有一个问题:就是提出申请的客户端在得到响应之后会更新,但是没有提出申请的客户端可能票被服务器拿走了他还不知道,所以不防做一个标记(这是由楼上那位朋友得到的启发),这个标记由服务器发放票的时候一起发给客户端,当服务器再重新调配的时候要改这个标记,客户端再卖票的时候要先查询一下本地的票时,就让它先查看一下标记,如果标记没变,那么就没关系,如果标记变了,就要更新。  我讲的大体上的思路就是这样的,也可能我讲得比较模糊,也可能你看起来比较模糊,有什么问题你可以再贴出来或发邮件给我都行([email protected]),我有时间就会看的,一起探讨探讨~~~
      

  9.   

    其实你说的这些办法都有想过了,但这些作法都会增加一些不必要的性能开销
    而且还是不能彻底解决问题
    我的实际问题是这样的,如下:
    一棵树的数据库结构,表明tree
    id  name     parentId parentPath childNum 
    1   根节点   0        |0|         2 
    2   文件夹1  1        |0|1|       1
    3   文件夹2  1        |0|1|       1 
    4   文件1    2        |0|1|2|     0
    5   文件2    3        |0|1|3|     0
    现在,假设A客户端在(文件夹1)下添加了一个(文件111)
    那A发给服务器端的sql="insert into tree(name,parentId,parentPath,childNum) values('文件111',2,'|0|1|2|',0)||update tree set childNum=childNum+1 where id=2"
    现在假设提交成功,新的表为
    id  name     parentId parentPath childNum 
    1   根节点   0        |0|         2 
    2   文件夹1  1        |0|1|       2
    3   文件夹2  1        |0|1|       1 
    4   文件1    2        |0|1|2|     0
    5   文件2    3        |0|1|3|     0
    6   文件111  2        |0|1|2|     0
    现在问题来了,假设在提交这个更新的过程中(假设在网络传输的过程中)B客户端删除了id=2的节点,那id=6的这条纪录就成了脏数据,永远无法在树上被正常的显示了,更严重的是,现在统计整个childNum字段已经d得不到正确的结果了,当然这种情况发生的机率很小,但只要发生一次,整个数据库的完整性就被破坏了
      

  10.   

    奥,你讲的那个关于卖票的系统那样解决是可以的,现实中的一些类似的系统实际上也没有处理这个细节,都是到了开销售单的时候再访问数据库然后决定有没有票卖,至于失信于客户的问题这个就只能说抱歉了,那种情况毕竟不会造成数据库完整性的破坏
    但你看你上面这个树的实际问题,只要有一次更新错误,就导致数据库结构的崩溃以及客户端的不正常显示
    很明显,这个问题不能用你提的解决方案来解决
    事实上,我们现在是用存储过程来解决这个问题的
    就是当作增删改操作的时候,先执行
    select id from tree where name=当前节点.名 and parentId=当前节点.parentId  and parentpath=当前节点.parentPath and childNum=当前节点.childNum
    如果找到这条纪录,则继续执行后面的操作,如果没有,说明当前节点已经被移动,修改,或重命名,或删除了。这时再刷新提交请求的客户端
    但是,大多数情况下,当前节点不会被移动,修改,或重命名,或删除的,所以每次执行以上的select变成了一种额外的开销
    理想化的解决方案就是:像在线聊天室那样,服务器上的数据改变,就主动改变客户端的显示,不知道能不能这样实现