Java----使用线程(synchronized)

来源:互联网 发布:庄子諵哗 知乎 编辑:程序博客网 时间:2024/06/05 18:11

以前编程没有怎么接触过synchronized方法,不太了解,今天编程遇到了多个线程访问同一个共享资源的问题,google了下synchronized使用方法,网上有二种说法,第一种说法是当一个线程访问了某个对象中的synchronzied方法,其它线程可以继续访问其它的synchronized方法,第二个说法与第一种说法相反,不能访问。搞的我也不确定,更要命的是,这两种说法在网上一边又一边的转载,以讹传讹,要误导不少java新手。到底那一个是正确的,编个程序验证就清楚了。 

   下面是一个示例程序,有三个角色,一个家庭中的父亲,母亲,和儿子,同时在ATM取款机上向同一个银行账号进行取钱和查询的操作  



1.银行类

Java代码  
  1. package com.sunnylocus.test;   
  2.   
  3. public class Bank  {   
  4.     private int money = 100;   
  5.     //取钱   
  6.     public synchronized void takeMoney(int num) {   
  7.             Thread.sleep(1000 * 5);   //取钱需要5秒   
  8.             money -= num;   
  9.     }   
  10.     //存钱   
  11.     public synchronized void addMoney(int num) {   
  12.             Thread.sleep(1000 * 10); //存钱需要10秒   
  13.             money += money;   
  14.     }   
  15.     //查询   
  16.     public int queryMoney() {   
  17.         return money;   
  18.     }   
  19. }  

 


2.父亲类

Java代码  
  1. package com.sunnylocus.test;   
  2.   
  3. import java.text.DateFormat;   
  4. import java.text.SimpleDateFormat;   
  5. import java.util.Date;   
  6.   
  7. public class Father extends Thread{   
  8.     private Bank bank;   
  9.     private int num;   
  10.        
  11.     DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象   
  12.        
  13.     public Father(Bank bank,int num) {   
  14.         this.bank = bank;   
  15.         this.num = num;   
  16.     }   
  17.   
  18.     public void run() {   
  19.         System.out.println("老爸正在取钱...      --"+dateFormate.format(new Date()));   
  20.         bank.takeMoney(num);   
  21.         System.out.println("老爸取走了"+num +"         --"+dateFormate.format(new Date()));   
  22.     }   
  23.        
  24. }  



3.母亲类

Java代码  
  1. package com.sunnylocus.test;   
  2.   
  3. import java.text.DateFormat;   
  4. import java.text.SimpleDateFormat;   
  5. import java.util.Date;   
  6.   
  7. public class Monther extends Thread{   
  8.     private Bank bank;   
  9.     private int num;   
  10.     DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象   
  11.        
  12.     public Monther(Bank bank,int num) {   
  13.         this.bank = bank;   
  14.         this.num = num;   
  15.     }   
  16.   
  17.     public void run() {   
  18.         System.out.println("老妈正在取钱....         "+dateFormate.format(new Date()));   
  19.         bank.takeMoney(num);   
  20.         System.out.println("老妈取走了"+num+"         --"+dateFormate.format(new Date()));   
  21.     }   
  22.        
  23. }  



4.儿子类

Java代码  
  1. package com.sunnylocus.test;   
  2.   
  3. import java.text.DateFormat;   
  4. import java.text.SimpleDateFormat;   
  5. import java.util.Date;   
  6.   
  7. public class Sun extends Thread{   
  8.     private Bank bank;   
  9.     DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象   
  10.     public Sun(Bank bank) {   
  11.         this.bank = bank;   
  12.     }   
  13.   
  14.     public void run() {   
  15.         //查询余款   
  16.         System.out.println("儿子查询余额:"+bank.queryMoney() +"     --"+dateFormate.format(new Date()));   
  17.     }   
  18. }  



5.测试类

Java代码  
  1. package com.sunnylocus.test;   
  2.   
  3. public class Main {   
  4.     public static void main(String[] args) {   
  5.         //银行   
  6.         Bank bank = new Bank();   
  7.         //老爸   
  8.         Father father = new Father(bank,50);   
  9.         //老妈   
  10.         Monther monther = new Monther(bank,100);   
  11.         //儿子   
  12.         Sun sun = new Sun(bank);   
  13.            
  14.         new Thread(father).start();   
  15.         new Thread(monther).start();   
  16.         new Thread(sun).start();   
  17.            
  18.     }   
  19. }  


输出结果:

Java代码  
  1. 老爸正在取钱...               --上午 11:52:01  
  2. 老妈正在取钱....              --上午 11:52:01  
  3. 儿子查询余额:100           --上午 11:52:01  
  4.   
  5. 老爸取走了50                 --上午 11:52:06  
  6. 老妈取了30                    --上午 11:52:11  


   一共有三个线程,同时启动,父亲线程和母亲线程同时取款的操作,因为父亲线程已经占用了对象锁,所以母亲线程只能等到父亲执行完方法释放锁后,才能执行。即便父亲线程占用了对象锁,儿子线程也能调用非synchronzied方法
 

     我们把母亲类的取钱的方法改成存钱的操作,虽然不是同一个synchronized方法.也一样不能执行,必须等到父亲线程方法执行完毕后,才能进行存钱的操作

我的结论: 
     synchronized method(){}可以防止多个线程同时访问这个对象的synchronized方法,如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法,那么其它线程不能同时访问这个对象中的任何一个synchronized方法,但可以访问这个对象中的非synchronized方法。
 

0 0
原创粉丝点击