synchronized实现线程锁

这里通过三个测试类阐述了synchronized应用的不同场景

 

首先是最基本的synchronized Method的使用

  1. package com.jadyer.thread.sync; 
  2.  
  3. /** 
  4.  * Synchronized Method Test 
  5.  * @see =================================================================================================== 
  6.  * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) 
  7.  * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 
  8.  * @see      当某个线程访问某个对象的synchronized方法时,则表示将该对象上锁 
  9.  * @see      此时其它的任何线程,均无法访问该对象中的任何一个synchronized方法(但允许访问该对象中的非synchronized方法) 
  10.  * @see      直到该线程所访问的synchronized方法执行完毕(或者抛出了异常)之后,该对象的锁才会被释放 
  11.  * @see      此时其它的任何线程,才被允许访问该synchronized方法,或者是该对象中的其它synchronized方法 
  12.  * @see =================================================================================================== 
  13.  * @see 总结:如果一个对象有多个synchronized方法,某一时刻某个线程已经执行了该对象中的某一个synchronized方法 
  14.  * @see      那么在该方法没有执行完毕之前,其它线程是无法访问该对象中的,包括该方法在内的,任何一个synchronized方法 
  15.  * @see      重点在于判断Synchronized锁的是谁。如果该方法是静态的,则锁Class对象,否则锁的就是当前对象 
  16.  * @see =================================================================================================== 
  17.  * @see 补充:1)这只是针对多个线程操作同一个类的同一个对象的情况。www.linuxidc.com若多个线程操作同一个类的不同对象,则不存在这种情况 
  18.  * @see      2)Java中的volatile变量也可以看作是一种"程度较轻的synchronized" 
  19.  * @see        关于volatile的更多信息,请参考http://www.ibm.com/developerworks/cn/java/j-jtp06197.html 
  20.  * @see 备注:实际项目中,用到的更多的还是JDK5.0开始推出的Java并发包,即java.util.concurrent包里面的工具类 
  21.  * @see      java.util.concurrent可以非常细粒度的实现并发。比如线程访问到了一个已被锁的对象,它可以让这个线程等到10秒 
  22.  * @see      10秒后如果该对象仍未被解锁,那么就可以返回给用户超时的提示等,而如果使用synchronized则是无法这么精确控制的 
  23.  * @see =================================================================================================== 
  24.  * @see 注意:1)当synchronized方法执行完或者发生异常时,会自动释放锁 
  25.  * @see      2)被synchronized保护的数据应该是private的,否则也就没必要去通过方法来访问这个public的数据了 
  26.  * @see =================================================================================================== 
  27.  * @author 宏宇 
  28.  * @create Feb 21, 2012 5:29:39 PM 
  29.  */ 
  30. public class SynchronizedTest { 
  31.     public static void main(String[] args) { 
  32.         Bank bank = new Bank(); 
  33.          
  34.         Thread tt11 = new Thread(new ThreadRMB(bank)); 
  35.          
  36.         //new一个新的Bank对象。此时存在两个Bank对象,并且它们属于同一个类的不同的对象  
  37.         //如要验证多个线程操作同一个类的不同的对象的synchronized方法,只需取消注释该行代码即可  
  38.         //bank = new Bank();  
  39.          
  40.         Thread tt22 = new Thread(new ThreadDollar(bank)); 
  41.          
  42.         tt11.start(); 
  43.         tt22.start(); 
  44.     } 
  45.  
  46.  
  47. class ThreadRMB implements Runnable{ 
  48.     private Bank bank; 
  49.     public ThreadRMB(Bank bank){ 
  50.         this.bank = bank; 
  51.     } 
  52.     @Override 
  53.     public void run() { 
  54.         bank.getRMB(); 
  55.     } 
  56.  
  57.  
  58. class ThreadDollar implements Runnable{ 
  59.     private Bank bank; 
  60.     public ThreadDollar(Bank bank){ 
  61.         this.bank = bank; 
  62.     } 
  63.     @Override 
  64.     public void run() { 
  65.         bank.getDollar(); 
  66.     } 
  67.  
  68.  
  69. class Bank{ 
  70.     public synchronized void getRMB(){ 
  71.         for(int i=0; i<20; i++){ 
  72.             try { 
  73.                 Thread.sleep((long)(Math.random()*1000)); 
  74.             } catch (InterruptedException e) { 
  75.                 e.printStackTrace(); 
  76.             } 
  77.             System.out.println(Thread.currentThread().getName() + ":" + i); 
  78.         } 
  79.     } 
  80.      
  81.     public synchronized void getDollar(){ 
  82.         for(int i=0; i<20; i++){ 
  83.             try { 
  84.                 Thread.sleep((long)(Math.random()*1000)); 
  85.             } catch (InterruptedException e) { 
  86.                 e.printStackTrace(); 
  87.             } 
  88.             System.out.println(Thread.currentThread().getName() + ":" + i); 
  89.         } 
  90.     } 
  91. 下面演示的是synchronized static Method的使用
    1. package com.jadyer.thread.sync;  
    2.   
    3. /** 
    4.  * Synchronized Static Method Test 
    5.  * @see 说明:如果某个synchronized方法是static的 
    6.  * @see      那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是该方法所在的对象所对应的Class对象 
    7.  * @see      因为Java中无论一个类有多少个对象,这些对象都会对应唯一的一个Class对象 
    8.  * @see      因此当线程分别访问同一个类的两个对象的两个static的synchronized方法时,它们的执行顺序也是顺序执行的 
    9.  * @see      即一个线程先执行一个static的synchronized方法,执行完毕后,另一个线程才开始执行另一个static的synchronized方法 
    10.  * @see 总结:重点在于判断synchronized锁的是谁。www.linuxidc.com如果该方法是静态的,则锁Class对象,否则锁的就是当前对象 
    11.  * @author 宏宇 
    12.  * @create Feb 21, 2012 5:29:39 PM 
    13.  */  
    14. public class SynchronizedStaticTest {  
    15.     public static void main(String[] args) {  
    16.         Bank bank = new Bank();  
    17.           
    18.         Thread tt11 = new Thread(new ThreadRMB(bank));  
    19.         Thread tt22 = new Thread(new ThreadDollar(bank));  
    20.           
    21.         tt11.start();  
    22.         tt22.start();  
    23.     }  
    24. }  
    25.   
    26.   
    27. class ThreadRMB implements Runnable{  
    28.     private Bank bank;  
    29.     public ThreadRMB(Bank bank){  
    30.         this.bank = bank;  
    31.     }  
    32.     @Override  
    33.     public void run() {  
    34.         bank.getRMB();  
    35.     }  
    36. }  
    37.   
    38.   
    39. class ThreadDollar implements Runnable{  
    40.     private Bank bank;  
    41.     public ThreadDollar(Bank bank){  
    42.         this.bank = bank;  
    43.     }  
    44.     @Override  
    45.     public void run() {  
    46.         bank.getDollar();  
    47.     }  
    48. }  
    49.   
    50.   
    51. class Bank{  
    52.     //如要验证synchronized锁同一个类的对象,和锁它的Class对象的区别   
    53.     //可去掉static关键字,再查看控制台打印,即public synchronized void getRMB()   
    54.     public synchronized static void getRMB(){  
    55.         for(int i=0; i<20; i++){  
    56.             try {  
    57.                 Thread.sleep((long)(Math.random()*1000));  
    58.             } catch (InterruptedException e) {  
    59.                 e.printStackTrace();  
    60.             }  
    61.             System.out.println(Thread.currentThread().getName() + ":" + i);  
    62.         }  
    63.     }  
    64.       
    65.     public synchronized static void getDollar(){  
    66.         for(int i=0; i<20; i++){  
    67.             try {  
    68.                 Thread.sleep((long)(Math.random()*1000));  
    69.             } catch (InterruptedException e) {  
    70.                 e.printStackTrace();  
    71.             }  
    72.             System.out.println(Thread.currentThread().getName() + ":" + i);  
    73.         }  
    74.     }  
    75. }  
    76. 最后演示的是synchronized Block的使用
      1. package com.jadyer.thread.sync;  
      2.   
      3. /** 
      4.  * Synchronized Block Test 
      5.  * @author 宏宇 
      6.  * @create Feb 21, 2012 5:29:39 PM 
      7.  */  
      8. public class SynchronizedBlockTest {  
      9.     public static void main(String[] args) {  
      10.         Bank bank = new Bank();  
      11.           
      12.         Thread tt11 = new Thread(new ThreadRMB(bank));  
      13.           
      14.         //如果要验证synchronized(this)锁的是当前类的对象,而非当前类的Class对象   
      15.         //则可取消注释该行代码,再观察控制台打印效果。效果应该是两个线程并发执行的输出   
      16.         //bank = new Bank();   
      17.           
      18.         Thread tt22 = new Thread(new ThreadDollar(bank));  
      19.           
      20.         tt11.start();  
      21.         tt22.start();  
      22.     }  
      23. }  
      24.   
      25.   
      26. class ThreadRMB implements Runnable{  
      27.     private Bank bank;  
      28.     public ThreadRMB(Bank bank){  
      29.         this.bank = bank;  
      30.     }  
      31.     @Override  
      32.     public void run() {  
      33.         bank.getRMB();  
      34.     }  
      35. }  
      36.   
      37.   
      38. class ThreadDollar implements Runnable{  
      39.     private Bank bank;  
      40.     public ThreadDollar(Bank bank){  
      41.         this.bank = bank;  
      42.     }  
      43.     @Override  
      44.     public void run() {  
      45.         bank.getDollar();  
      46.     }  
      47. }  
      48.   
      49.   
      50. /** 
      51.  * Bank 
      52.  * @see 说明:synchronized块的写法:synchronized(object){//TODO...},它表示线程在执行的时候,会对object对象上锁 
      53.  * @see      通常会把java.lang.Object对象传进来,事实上这里可以传进来任何的对象 
      54.  * @see      因为它是一个没有实际作用的对象,其仅仅起到锁的作用,就像一个标识一样 
      55.  * @see 作用:它表示,如果线程能够进入到这里,即执行到这里,那么,就将object对象锁上 
      56.  * @see      如果另一个线程也执行到这里,发现object对象已上锁,则会等待其解锁后,才会去执行synchronized块里面的代码 
      57.  * @see 补充:synchronized(this)表示对当前类的对象上锁。注意,它锁的不是当前类的Class对象 
      58.  * @see      synchronized(Bank.class)表示对当前类的Class对象上锁 
      59.  * @author 宏宇 
      60.  * @create Feb 22, 2012 2:29:16 AM 
      61.  */  
      62. class Bank{  
      63.     private Object obj11 = new Object();  
      64.     private Object obj22 = new Object();  
      65.       
      66.     public void getRMB(){  
      67.         //synchronized(obj11){   
      68.         synchronized (Bank.class) {  
      69.             for(int i=0; i<20; i++){  
      70.                 try {  
      71.                     Thread.sleep((long)(Math.random()*1000));  
      72.                 } catch (InterruptedException e) {  
      73.                     e.printStackTrace();  
      74.                 }  
      75.                 System.out.println(Thread.currentThread().getName() + ":" + i);  
      76.             }  
      77.         }  
      78.     }  
      79.       
      80.     public void getDollar(){  
      81.         //synchronized(obj11){   
      82.         //synchronized(obj22){   
      83.         synchronized (this) {  
      84.             for(int i=0; i<20; i++){  
      85.                 try {  
      86.                     Thread.sleep((long)(Math.random()*1000));  
      87.                 } catch (InterruptedException e) {  
      88.                     e.printStackTrace();  
      89.                 }  
      90.                 System.out.println(Thread.currentThread().getName() + ":" + i);  
      91.             }  
      92.         }  
      93.     }  
      94. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值