文档目录:安全
1、概念多线程
2、解决方案并发
3、举例说明ide
---------------------------------------分割线:正文--------------------------------------------------------测试
1、概念this
关注数据在多线程并发时安全问题,共享数据有修改的行为。spa
2、解决方案线程
一、线程排队执行,不能并发,即线程同步机制。code
二、使用synchronized(){}线程同步代码块,()内填写须要同步的共享对象对象
三、局部变量永远不存在线程安全问题,由于局部变量是不会共享的
3、举例说明
一、编写程序模拟两个线程同时对同一个帐户进行去取款操做
(1)变成帐户类
1 package JAVAADVANCE; 2
3 public class Account { 4 //帐户与余额
5 private String actNo; 6 private double balance; 7
8 public Account(String actNo, double balance) { 9 this.actNo = actNo; 10 this.balance = balance; 11 } 12
13 public String getActNo() { 14 return actNo; 15 } 16
17 public void setActNo(String actNo) { 18 this.actNo = actNo; 19 } 20
21 public double getBalance() { 22 return balance; 23 } 24
25 public void setBalance(double balance) { 26 this.balance = balance; 27 } 28 //取款
29 public void withdraw(double money){ 30 //取款以前的余额
31 double before=this.getBalance(); 32 //取款以后的余额
33 double after = before-money; 34 //更新余额
35 this.setBalance(after); 36 } 37
38 }
(2)编写帐户线程类
1 package JAVAADVANCE; 2
3 public class AccountThread extends Thread { 4 //两个线程必须共享同一个帐户对象
5 private Account act; 6 //经过构造方法传递过来的帐户对象
7 public AccountThread(Account act){ 8 this.act=act; 9 } 10 @Override 11 public void run() { 12 //run方法执行表示取款操做 13 //假设取款5000
14 double money=5000; 15 //取款
16 act.withdraw(money); 17 System.out.println(Thread.currentThread().getName()+"对帐户"+act.getActNo()+"取款成功,余额为:"+act.getBalance()); 18 } 19 }
(3)测试类进行取款操做
1 package JAVAADVANCE; 2
3 public class TestAdvance38TestThreadSafe01 { 4 public static void main(String[] args) { 5 //建立帐户对象,只建立一个
6 Account act=new Account("act-001",10000); 7 //建立两个线程
8 Thread t1=new AccountThread(act); 9 Thread t2=new AccountThread(act); 10 //设置name
11 t1.setName("t1"); 12 t2.setName("t2"); 13 //启动线程取款
14 t1.start(); 15 t2.start(); 16 } 17
18 }
(4)查看运行结果,必定概率出现钱被取完,余额未更新,出现线程安全问题
t2对帐户act-001取款成功,余额为:5000.0 t1对帐户act-001取款成功,余额为:5000.0
二、改进代码,使用线程同步机制来解决以上问题
(1)加入synchronized ()线程同步代码块
()内须要填写多线程共享的数据,才能达到多线程排队。
1 //取款
2 public void withdraw(double money){ 3 //增长线程同步机制,里面是线程同步代码块
4 synchronized (this){ 5 //取款以前的余额
6 double before=this.getBalance(); 7 //取款以后的余额
8 double after = before-money; 9 try { 10 Thread.sleep(1000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 //更新余额
15 this.setBalance(after); 16 } 17
18 }
改进后再次执行,多线程不会并发
t1对帐户act-001取款成功,余额为:5000.0 t2对帐户act-001取款成功,余额为:0.0
(2)whithdraw调用时候增长,synchronized ()线程同步代码块,扩大了同步范围,执行效率变低
1 @Override 2 public void run() { 3 //run方法执行表示取款操做 4 //假设取款5000
5 double money=5000; 6 //取款
7 synchronized (act){ 8 act.withdraw(money);} 9 System.out.println(Thread.currentThread().getName()+"对帐户"+act.getActNo()+"取款成功,余额为:"+act.getBalance()); 10 }
执行效果同上:多线程不会并发
(3)将实例方法使用synchronized
缺点:必定须要锁this,整个方法体都须要同步,可能会扩大同步范围致使程序效率太低
有点:代码比较少,简介
1 //取款
2 public synchronized void withdraw(double money){ 3 //增长线程同步机制,里面是线程同步代码块 4 // synchronized (this){ 5 //取款以前的余额
6 double before=this.getBalance(); 7 //取款以后的余额
8 double after = before-money; 9 try { 10 Thread.sleep(1000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 //更新余额
15 this.setBalance(after); 16 }