java进阶(38)--线程安全

文档目录:安全

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         }
相关文章
相关标签/搜索