问题描述
首先,祝大家伙节日快乐大过节的,又要麻烦大家了。不过,我觉得这是很经典的一个例子,希望大伙能一起瞧瞧
我先说明一下意思银行类里面有两个方法,transfer()和getTotalBalance()他们用的是同一把锁,在实例化该类的时候产生我的主要困惑在于,当一个线程进入transfer()方法的时候,他获得了锁,但是他同时调用了getTotalBalance()方法System.out.printf("TotalBalance:%10.2f%n",getTotalBalance());可是,这个方法也是需要锁的,而且他们用的是同一把锁publicdoublegetTotalBalance(){Bank_TestLock.lock();try{doublesum=0;for(doublea:accounts)sum+=a;returnsum;}finally{Bank_TestLock.unlock();}}那么,当我执行上面代码的时候,到底发生了什么呢,还请大侠们明示!
解决方案
解决方案二:
lock/unlock里面的内容是什么啊?
解决方案三:
锁的含义,相信你是明白的,锁是为了独占某个资源,当A资源被占用之后,如果有别的线程希望占用A资源,那么就需要等到资源释放.在这里的话,当你执行getTotalBlance就是代表着,当你计算总收支平衡的时候,不允许对账户进行操作,以避免你计算错误,例如甲乙两个账户,你计算了甲账户之后,从甲账户汇了钱到乙账户,如果你不暂停对所有账户的操作,那么你在计算乙账户的时候,重复的计算了刚汇来的那笔钱,得到的结果就是错误的
解决方案四:
兄台,你的意思我明白。我分析一下思路吧,当甲调用了transfer方法,获得了锁,他在里面进行了汇款给乙,甲的钱少了,乙的钱多了,然后他想计算总的存款量,他又要调用getTotalBalance()方法,这个方法也是需要锁的,可是甲的锁是在finally里面释放的(见代码),那么甲进入getTotalBalance()方法的时候,他获取的是哪一把锁呢。我这里的锁是基于Bank_Test的某一个实例的,因为甲,乙是操作的同一个实例的内容,所以肯定是用的同一把锁我的主要困惑是,在调用getTotalBalance()方法的时候怎么去理解甲的锁还没有释放,还请兄台明示!
解决方案五:
引用3楼HOLLYWOOD2012的回复:
兄台,你的意思我明白。我分析一下思路吧,当甲调用了transfer方法,获得了锁,他在里面进行了汇款给乙,甲的钱少了,乙的钱多了,然后他想计算总的存款量,他又要调用getTotalBalance()方法,这个方法也是需要锁的,可是甲的锁是在finally里面释放的(见代码),那么甲进入getTotalBalance()方法的时候,他获取的是哪一把锁呢。我这里的锁是基于Bank_Test的某一个实例的,因为甲,乙是操作的同一个实例的内容,所以肯定是用的同一把锁我的主要困惑是,在调用getTotalBalance()方法的时候怎么去理解甲的锁还没有释放,还请兄台明示!
你可以理解为,在getTotalBalance()中,我们去想系统申请说,诶,系统,我要一个人占用某个资源;如果系统中有人已经占用了,然后系统就说,现在有人在使用,你先等着吧,然后我们就只要在那儿等着系统释放资源,然后拿到了系统的允许之后再向下执行
解决方案六:
楼主能解释下具体解释下什么意思吗?当一个线程进入transfer()方法的时候,他获得了锁。获得了哪个对象的锁?这个银行类需要操作具体的客户类?获得的锁是什么锁。
解决方案七:
晕,现在才出现代码
解决方案八:
请别截图好么使用代码格式粘贴,大家都会很好看。复制代码放到那个两个code标签之间,就这么简单。
解决方案九:
引用一下楼主的原话我的主要困惑在于,当一个线程进入transfer()方法的时候,他获得了锁,但是他同时调用了getTotalBalance()方法System.out.printf("TotalBalance:%10.2f%n",getTotalBalance());可是,这个方法也是需要锁的,而且他们用的是同一把锁。。。。。。那么,当我执行上面代码的时候,到底发生了什么呢,还请大侠们明示!你是没理解清楚同步锁的含义。首先,是线程获取锁,而不是transfer()或者是getTotalBalance()方法获取锁。理论上来说,一个线程可以多次对同一个对象上锁。对于每一个对象,java虚拟机维护一个加锁计数器,线程每获得一次该对象,计数器就加1,每释放一次,计数器就减1,当计数器值为0时,锁就被完全释放了。所以,是这个线程获取了同一个对象的两次锁。你问会发生什么?答案是:在同一个线程中transfer()和getTotalBalance()方法不会起到同步的效果。代码跑到哪里就运行什么,第二次look是没效果的。为什么说是理论上呢?因为我实在想不出你的look/unlook代码是怎么写的。。。我想到的线程同步,首先是synchronized关键字。你这look/unlook用法,怎么看也不像是用synchronized关键字。
解决方案十:
小弟初来乍到,如果在格式上有什么不妥,我下次一定改正不过看后@全小范的回答,我又在网上查了一下,我应该是明白了其实大家不用纠结我具体在干什么,如果大家能仔细听我说的话,其实事情是这样的:线程甲乙共同操作一个类的实例对象,线程甲此时进入transfer()方法,拿到了对象的锁,他便开始运行代码,然后,他会调用一个方法getTotalBalance(),问题就出来了,那么这个方法需要同步吗?如小范所说,可以不用同步,因为这个方法是在甲拿到锁之后,释放锁之前调用的,他是同步的,也就是说线程甲必须执行完这个方法,如果transfer()还需要调用其他方法,那个方法也必须被执行完,依次类推。接下来的问题,如果getTotalBalance()里面也调用了Lock.lock()呢?好的,这样也是可以的,因为一个线程可以对同一对象多次上锁,如果getTotalBalance()里面被线程上了锁,他执行完之后这个锁必须被释放,对于每一个对象,虚拟机会有一个加锁计数器,你加一次锁,计数加一,一个对象的锁真正被释放就意味着计数器必须为0(我还不清楚加锁和解锁是不是必须要对应),我的大致想法如下,有什么错误,恳请指出,大家一起学习!
解决方案十一:
楼主是来给大家讲课还是来问问题啊?
解决方案十二:
引用8楼u010342936的回复:
引用一下楼主的原话我的主要困惑在于,当一个线程进入transfer()方法的时候,他获得了锁,但是他同时调用了getTotalBalance()方法System.out.printf("TotalBalance:%10.2f%n",getTotalBalance());可是,这个方法也是需要锁的,而且他们用的是同一把锁。。。。。。那么,当我执行上面代码的时候,到底发生了什么呢,还请大侠们明示!你是没理解清楚同步锁的含义。首先,是线程获取锁,而不是transfer()或者是getTotalBalance()方法获取锁。理论上来说,一个线程可以多次对同一个对象上锁。对于每一个对象,java虚拟机维护一个加锁计数器,线程每获得一次该对象,计数器就加1,每释放一次,计数器就减1,当计数器值为0时,锁就被完全释放了。所以,是这个线程获取了同一个对象的两次锁。你问会发生什么?答案是:在同一个线程中transfer()和getTotalBalance()方法不会起到同步的效果。代码跑到哪里就运行什么,第二次look是没效果的。为什么说是理论上呢?因为我实在想不出你的look/unlook代码是怎么写的。。。我想到的线程同步,首先是synchronized关键字。你这look/unlook用法,怎么看也不像是用synchronized关键字。
首先比较同意是线程获取了锁,lock是一把锁多个监视器,这个比synchronized强大了很多,但是似乎也麻烦了不少了,synchronized将同步和锁绑定在一起了。