银行存钱问题:
//CPU会切换的点不是每一行代码执行完,而是每一个运算执行完
多线程关注的点:(多线程)共享数据和共享数据被多个运算操作
完整正确的代码:
package Thread;
/*
需求:
两个用户到银行去存钱,每个客户每次存100,存三次
问:该程序是否有安全问题,如果有请解决
*/
//描述银行
class Bank{
private int sum;
private Object obj = new Object();
public void add(int money){
synchronized (obj) {
sum = sum + money;
System.out.println(Thread.currentThread().getName() + " sum = " + sum);//每存一次,输出银行的金额变化
}
}
}
class Consumer implements Runnable{
private Bank b = new Bank();//最后发生金额变化的是一个银行
public void run(){
for(int x=1;x<=5;x++){
b.add(100);
}
}
}
public class ThreadBank {
public static void main(String[] args){
Consumer c =new Consumer();//线程任务/两条线程执行的线程任务是一样的,各自的数据不同(在各自的栈空间中存储)
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start() ;
t2.start();
}
}
总结:
1.这段程序是满足同步的要求的:
共享数据被两条线程操作,并且有多个语句操作共享数据
如果不加同步会出现的问题:例如金额在线程0 加到200时CPU切换到线程1完成完整的的操作此时金额变为300并且输出。CPU再回到线程0接着执行输出金额也会输出300。200这个数据就会缺失。
2.在代码书写时的小细节:
-
锁是写在操作共享数据的代码行的,重要的是,要找到共享数据并且找到对它的几行操作代码将其同步
-
对于线程任务实例化,因为两个线程执行的线程任务是一样的(要走的流程是一样的)所以在创建线程时传入的是一样的线程任务对象(这里解释一下:线程任务相当于流程,但具体执行成什么样子,每条线程是不一样的,他们的数据都在自己的栈线程空间内存储)