3-3-Java多线程-案例-银行存钱&同步函数
来源:互联网 发布:苹果mac好用吗 编辑:程序博客网 时间:2024/04/30 13:42
银行存钱案例
- 两个客户到一个银行去存钱,每个客户一次存100,存三次。
- 问题:改程序是否有安全问题,如果有写出分析过程并定义解决方案
代码示例-未修改前
代码
class Bank{ private int sum; private Object obj = new Object(); public void add(int num) { sale(num); } /** * 需要同步的同步函数 * @param num */ private /*synchronized*/ void sale(int num) { sum = sum+num; /* 此处可能发生CPU切换 */ System.out.println("sum " + sum); }}class Consumer implements Runnable{ private Bank bank = new Bank(); public void run() { for (int i = 0 ; i < 3 ; i ++) { bank.add(100); } }}public class ThreadDemo{ public static void main(String[] args) { Consumer consumer = new Consumer(); Thread t1 = new Thread(consumer); Thread t2 = new Thread(consumer); t1.start(); t2.start(); }}
运行结果
sum 200sum 200sum 300sum 400sum 500sum 600
分析
问题来源
- 既然是多线程问题,必然发生在线程任务内
- 任务代码中是否有共享数据呢? 操作此数据的代码时候有多条任务呢?
private Bank bank = new Bank();public void run() { for (int i = 0 ; i < 3 ; i ++) { bank.add(100); }}private int sum;private /*synchronized*/ void sale(int num){ sum = sum+num; /* 此处可能发生CPU切换 */ System.out.println("sum " + sum);}
bank是共享数据,具体的讲,bank中的sum是共享数据,并且有多条代码操作此数据.
所以我们需要给操作共享变量的函数加同步
程序示例
class Bank{ private int sum; private Object obj = new Object(); public void add(int num) { sale(num); } /** * 同步函数 * @param num */ private synchronized void sale(int num) { sum = sum+num; /* 此处不再发生CPU切换 因为其他线程得不到锁*/ System.out.println("sum " + sum); }}class Consumer implements Runnable{ private Bank bank = new Bank(); public void run() { for (int i = 0 ; i < 3 ; i ++) { bank.add(100); } }}public class ThreadDemo{ public static void main(String[] args) { Consumer consumer = new Consumer(); Thread t1 = new Thread(consumer); Thread t2 = new Thread(consumer); t1.start(); t2.start(); }}
同步函数
- 同步的另外一个体现形式:同步函数 private synchronized void sale(int num)
- 同步函数使用this做锁 , 因为函数必须被对象调用
(可写一个同步代码块,写一个同步函数,同步代码块以this为锁,如果同步代码块中锁对象是同一个
,那么这一块代码不可被同步执行.)
class Ticket implements Runnable{ private int tickets = 100; private Object obj = new Object(); boolean flag = true; public void run() { if(flag){ while(true){ synchronized(this){ if(tickets>0){ try{Thread.sleep(10);}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+"...obj..."+tickets--);//打印线程名称。 } } } } else{ while(true){ this.sale(); } } } public synchronized void sale()//同步函数,使用的锁对象 this。 { if(tickets>0) { try{Thread.sleep(10);}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+"...sale..."+tickets--);//打印线程名称。 } }}class ThreadDemo4 { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(InterruptedException e){} //切换标记,之前,让主线程停一会,这时就只有一个t1线程在,它就会执行同步代码块。 t.flag = false; t2.start(); }}
同步函数和同步代码块有什么区别
- 同步函数使用的锁是固定的this。当线程任务中只需要一个同步时完全可以使用同步函数
- 同步代码块使用的锁是任意的对象。当线程任务中需要多个同步时,必须通过锁来区分
- 静态同步函数使用的锁不是this而是字节码文件对象 类名.class
(一般当只有一个锁时只用同步函数就可以)
静态同步函数的锁
静态同步函数使用.class对象做锁
/*static 同步函数,使用的锁不是this,而是字节码文件对象, 类名.class */class Ticket implements Runnable{ private static int tickets = 100; private Object obj = new Object(); boolean flag = true; public void run() { if(flag){ while(true){ synchronized(Ticket.class){ if(tickets>0){ try{Thread.sleep(10);}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+"...obj..."+tickets--);//打印线程名称。 } } } } else{ while(true){ this.sale(); } } } public static synchronized void sale()// { if(tickets>0) { try{Thread.sleep(10);}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+"...sale..."+tickets--);//打印线程名称。 } }}class ThreadDemo5 { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(InterruptedException e){} //切换标记,之前,让主线程停一会,这时就只有一个t1线程在,它就会执行同步代码块。 t.flag = false; t2.start(); }}
0 0
- 3-3-Java多线程-案例-银行存钱&同步函数
- 04.多线程--05.【多线程银行客户存钱案例设计】【同步函数基本用法和原理】
- 多线程——引用同步函数解决经典储户银行存钱问题
- 多线程——用同步代码块解决经典储户银行存钱问题
- 银行存钱
- 银行存钱
- 利用线程同步模拟一人向银行存钱,一人从银行取钱。
- 去银行存钱
- 再去银行存钱
- 顾客存钱到银行
- 《黑马程序员》java笔记->银行储户存钱线程练习
- java多线程存钱,取钱例子
- 银行账号同步多线程处理
- 多线程——多线程解决经储户银行存钱问题2
- Java 多线程 静态同步函数
- JAVA多线程静态同步函数
- Java笔记 - 多线程-同步函数
- java基础--while循环实现存钱问题案例
- android View事件分发
- 常见对象_Arrays工具类的概述和使用
- UVA1492 LA5694 线段树扫描线(矩形面积合并)
- .gitignore中增加过滤规则不起作用的解决方法
- 浅谈 Observable和Observer 观察者模式
- 3-3-Java多线程-案例-银行存钱&同步函数
- golang https服务简单介绍
- 4-1-JDK1.5-Lock接口
- 5-1-Java多线程-练习-妖的出现和解决
- teamviewer一些按键冲突
- Java Arrays.asList()方法详解
- sessionStorage 、localStorage 和 cookie 之间的区别
- amr转MP3(ffmpeg问题记录)
- 欢迎使用CSDN-markdown编辑器