package day6;
/**
* 需求:
* 现在有一个bank
* 有两个cus往银行中存钱
* 实现银行中金额的增加
*
* @author mzy
*
* 同步函数
*/
publicclassTest{
publicstaticvoidmain(String[]args){
Cuscus=newCus();
Threadt=newThread(cus);
Threadt1=newThread(cus);
t.start();
t1.start();
}
}
/**
* 因为bank中的add方法被cus多次调用,且为两位cus构成了多线程
* 如果不给add加锁的话,就会导致线程不安全出错
*
* @author mzy
*
*/
classBank{
privateintsum;
Objecto=newObject();
publicsynchronizedvoidadd(intn){
sum+=n;
try{
Thread.sleep(10);
}catch(Exceptione){
}
System.out.println("sum = "+sum);
}
}
classCusimplements Runnable{
privateBankb=newBank();
publicvoidrun(){
for(inti=0;i<3;i++){
b.add(100);
}
}
}
这里也就延续了同步代码块的问题,这里银行算账:如果不将run中的add方法抽离出来的话,为了保证线程安全,通过之前的内容,那么我们只有两种解决方法:
1. 将add所在的区域写成同步代码块的形式;(可以考虑,但是不能保证类的功能的单一性)
2. 将整个run方法都用synchronized修饰,这样run方法就变成了同步函数了,这样是很不合理的,纵使前面两个线程都开启了,但是其实自始至终,只有最开始进入的线程在执行。
所以这里最合理的方法就是使用同步函数的方式,将add抽离出来。
但是这里就有一个问题,因为最开始我们引入的时候,说明了同步是需要锁的,而且多个线程使用的必须是同一个锁,但是同步函数的调用的时候我我们只看见了传入的形参,并未看见传入的对象锁,这里需要说明的是同步函数的锁,是当前对象,我们都知道在调用对象内的方法时当前对象的this一般我们都会省略,除非变量名含糊不清时才会或者构造方法之间的互相调用时才会使用this关键字,其实在同步函数中的锁就是被我们省略的当前的对象。