发布网友 发布时间:2022-11-17 22:10
共3个回答
热心网友 时间:2024-11-23 11:55
楼主,其实两段代码都是有问题的(楼主可以增加循环次数,或者增加线程数量,或者在Bank.jinKu += 100;后添加Sleep语句,来增加异常情况出现的概率)。下面请看我分析第二段代码执行时为什么会出现这样的怪异结果:
楼主第二段代码的运行结果是:
运行结果为:-----分析(这里只针对上面结果提出一个可能的执行顺序,实际上还有很多其他执行顺序,会得到同样的结果):
1、线程aaa首次执行,执行了Bank.jinKu += 100;后,放弃时间分片(还未进入System.out.println方法),让线程kkk执行。(此时金库值为100);
2、线程kkk开始执行,执行了一次完整循环体(此时金库值为200)并打印第1行结果出来;
3、线程kkk放弃时间分片,由线程aaa继续执行,线程aaa继续执行System.out.println并传入与“200”(因为金库被kkk线程+了100)进行字符串链接操作后的参数,进入System.out.println方法后(还没有执行具体的打印方法),放弃时间分片,由线程kkk继续执行;
4、线程kkk获得时间分片继续执行一次完整循环体(此时金库值为300)并打印第2行结果出来;
5、线程kkk此时放弃时间分片,由线程aaa获得时间分片,aaa继续执行System.out.println方法,将第3行结果打印出来(请注意这里打印出来200是因为步骤3时已经传入了参数,进入System.out.println后,打印结果就跟变量Bank.jinKu无关了,因为变化的是Bank.jinKu,而传入的是经过字符串链接后产生的一个新的String类型对象,而且就算是String对象变化了,也不会影响到传入到方法中到String对象);
6、线程aaa放弃时间分片,由kkk继续执行一个完整循环体(此时金库值为400)并打印第4行结果出来;
7、线程kkk执行完毕,线程消亡,由线程aaa执行两次完整循环体,分别打印结果第5、6行;
请用同样的方法分析第一段代码可能出现的异常情况。
楼主使用了synchronized (new Object())来控制并发问题没有达到效果,因为new Object()每次都是生成不同的对象,不是同一个锁标记,因此多个线程还是可以同时访问这段(存钱的)代码。
为此楼主可以这样改进:
class Bank {同时,
synchronized (new Object())改成
synchronized (Bank.lock)
热心网友 时间:2024-11-23 11:55
估计是多线程数据共享乱了的问题,第二种你把它写在两个语句里执行的时候线程交叉了。热心网友 时间:2024-11-23 11:56
其实很正常,synchronized(new Object)等于没有锁定,因此两个线程同时运行了,就会出现你现在的情况。Bank.jinKu += 100; 两个线程同时运行了,结果都对,然后才执行System.out语句,这时,两次加都完成了,所以就这样了。