• 树森
    2019-03-07
    有个疑问,使用Account.class获得锁,那所有转账操作不是都成串行了,这里实践中可行吗?

    作者回复: 不可行,下一期讲优化

     2
     93
  • senekis
    2019-03-07
    解决原子性问题,是要保证中间状态对外不见

    太精辟了!
     3
     83
  • 少主江衫
    2019-03-07
    用this.balance 和this.password 都不行。在同一个账户多线程访问时候,A线程取款进行this.balance-=amt;时候此时this.balance对应的值已经发生变换,线程B再次取款时拿到的balance对应的值并不是A线程中的,也就是说不能把可变的对象当成一把锁。this.password 虽然说是String修饰但也会改变,所以也不行。老师所讲的例子中的两个Object无论多次访问过程中都未发生变化?
    请老师指正。

    作者回复: 正确,不能用可变对象做锁

    
     77
  • 夜空中最亮的星(华仔...
    2019-03-07
    我是一名普通的运维工程师,我是真看不懂java代码,我是来听思想的 。

    作者回复: 那我就放心了

     2
     42
  • 老杨同志
    2019-03-07
    思考题:
    我觉得不能用balance和password做为锁对象。这两个对象balance是Integer,password是String都是不可变变对象,一但对他们进行赋值就会变成新的对象,加的锁就失效了

    作者回复: 是的

     3
     32
  • 别皱眉
    2019-03-13
    老师,很感谢有这个专栏,让我能够更加系统的学习并发知识。
    对于思考题,之所以不可行是因为每次修改balance和password时都会使锁发生变化。
    -----------------------------------------------------------------------
    以下只是我的猜想
    比如有线程A、B、C
    线程A首先拿到balance1锁,线程B这个时候也过来,发现锁被拿走了,线程B被放入一个地方进行等待。
    当A修改掉变量balance的值后,锁由balance1变为balance2.
    线程B也拿到那个balance1锁,这时候刚好有线程C过来,拿到了balance2锁。
    由于B和C持有的锁不同,所以可以同时执行这个方法来修改balance的值,这个时候就有可能是线程B修改的值会覆盖掉线程C修改的值?
    -----------------------------------------------------------------------
    不知道到底是不是这样?老师可以详细讲下这个过程吗?谢谢
    展开

    作者回复: 你分析的很仔细了,就是这样的,bc锁的不是一个对象。不能保证互斥性

     1
     18
  • yuc
    2019-03-09
    是否可以在Account中添加一个静态object,通过锁这个object来实现一个锁保护多个资源,如下:
    class Account {
      private static Object lock = new Object();
      private int balance;
      // 转账
      void transfer(Account target, int amt){
        synchronized(lock) {
          if (this.balance > amt) {
            this.balance -= amt;
            target.balance += amt;
          }
        }
      }
    }
    展开

    作者回复: 这种方式比锁class更安全,因为这个缺是私有的。有些最佳实践要求必须这样做。👍

     3
     15
  • zhaozp
    2019-03-07
    可变对象不能作为锁

    作者回复: 总结的到位

    
     11
  • 强哥
    2019-03-07
    文章里第二个例子根本无法用到实践中,锁力度太大,可以用乐观关锁解决,另外分布式的情况下,应该如何分析也应该讲讲?至于原子性其实跟数据库的原子性还是有差异的,例如虚拟机异常退出时,synchinzed也无法操作原子操作的。

    作者回复: 分布式的不讲了,分支太多不好。下一期会讲优化

     1
     11
  • wang
    2019-03-07
    不可以。因为balance为integer对象,当值被修改相当于换锁,还有integer有缓存-128到127,相当于同一个对象。

    作者回复: 深刻!👍

    
     9
  • 0bug
    2019-03-07
    思考题:
    结论:不可行
    原因:举个例子,假如this.balance = 10 ,多个线程同时竞争同一把锁this.balance,此时只有一个线程拿到了锁,其他线程等待,拿到锁的线程进行this.balance -= 1操作,this.balance = 9。 该线程释放锁, 之前等待锁的线程继续竞争this.balance=10的锁,新加入的线程竞争this.balance=9的锁,导致多个锁对应一个资源

    作者回复: 分析的很仔细👍

    
     8
  • gogo
    2019-03-07
    王老师, 您在第二讲中贴出的英文链接的地址很棒,看着您写过的专栏,再去看它,有种恍然大悟地感觉~! 恳请您还是在后续地专栏里,继续保持这种死磕并发基础地原汁原味地链接啊~! 您地专栏是您多年地理解与实战的营养,加上您亲自地朗读,当然也是原汁原味。但是我的意思是,我们应该有一批人很少看英文类的文档,所以才会有这种恳请~! 谢谢老师~!

    作者回复: 感谢盛赞,我会继续保持的

    
     8
  • 峰
    2019-03-07
    思考题,我的答案是不行,因为对象可变,所以导致加锁对象不一样。

    然后感觉加锁的所有用户用同一个锁的粒度太大了,但如果每次转账操作,是不是可以同时加两个用户的锁,如果有先后顺序又可能有死锁问题。

    作者回复: 下一期会讲这个

    
     6
  • 忠艾一生
    2019-03-07
    这两把锁是会变的,所以无法保证互斥性。在第一个线程执行完之后,this.balance与this.password这两个对象锁都与第一个线程的对象锁是不一样的。 所以是不正确的。

    作者回复: 回答正确

    
     4
  • zyl
    2019-03-07
    请问这个画图软件是什么?谢谢

    作者回复: 我已经确认过了,是PPT

    
     4
  • 水如天
    2019-03-07
    以前碰到一个坑,线程上下文的类加载器改变了,导致前后加载的类不一致

    作者回复: osgi?

    
     3
  • walkingonair
    2019-03-07
    使用Account.class获得锁有很明显的性能问题,而如何解决这个性能问题恰恰是我想知道的。我的一个想法是利用String对象的intern方法生成转账相关的字符串,利用这个字符串作为锁,这个方案不知道在实践中是否可行?
    另外,狂战俄洛伊同学提出的锁两个对象的示例,我看着像是经典的死锁案例,因加锁顺序不一致导致的死锁,当A->B,A等待B的锁,而当B->A,B等待A的锁,产生死锁,不知理解的是否有问题,欢迎老师和各位同学指教。

    作者回复: 下一期介绍优化

    
     3
  • 245864982
    2019-09-29
    评论区都是大神,我在看的时候就在想,为什么不直接锁余额和密码字段要另外加个对象来锁。看了评论才明白。还有锁了整个class对象性能不是很低。令老师深懂我这种菜鸟的疑惑啊。很好

    作者回复: 因为我也曾经很菜😂

    
     2
  • 糖小宝
    2019-08-18
    有种冲动,跑上家公司把我以前写的逻辑改了。。。
    以前跟并发不熟TAT 谢谢老师开此专栏

    作者回复: 可以给上家推荐下专栏😄

    
     2
  • 知行合一
    2019-07-29
    老师,写的时候加锁能理解,读的时候为啥要加锁呢

    作者回复: 为了保证一定能读到最新的值

    
     2
我们在线,来聊聊吧