Android应用开发之synchronized

来源:互联网 发布:淘宝购物分享在哪里 编辑:程序博客网 时间:2024/06/07 10:04

        synchronized 是java语言关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。  

本文直接以代码的形式来展示 synchronized 关键字的使用:

【1】synchronized  Demo1:

[html] view plaincopy
  1. package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,  
  5.  * 一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码  
  6.  * 块以后才能执行该代码块。  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class Thread01 implements Runnable {  
  11.   
  12.     @Override  
  13.     public void run() {  
  14.   
  15.         synchronized (this) {  
  16.             for(int i=0;i<3;i++){  
  17.                 System.out.println(Thread.currentThread().getName()+" synchronized loop "+i);  
  18.             }  
  19.         }  
  20.     }  
  21.       
  22.     public static void main(String[] args) {  
  23.         Thread01 t01 = new Thread01();  
  24.           
  25.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  26.                   +"synchronized 关键字使用 \n"  
  27.                   +"--------------------------");  
  28.           
  29.         Thread ta = new Thread(t01,"A");  
  30.         Thread tb = new Thread(t01,"B");  
  31.           
  32.         ta.start();  
  33.         tb.start();  
  34.     }  
  35.   
  36. }  

运行结果如下:

[html] view plaincopy
  1. Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. B synchronized loop 0  
  5. B synchronized loop 1  
  6. B synchronized loop 2  
  7. A synchronized loop 0  
  8. A synchronized loop 1  
  9. A synchronized loop 2  

【2】synchronized  Demo2:

[html] view plaincopy
  1. package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * 当一个线程访问object的一个synchronized(this)同步代码块时,  
  5.  * 另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  
  6.  * @author Andy.Chen  
  7.  *  
  8.  */  
  9. public class Thread02 {  
  10.       
  11.     public void method01(){  
  12.         synchronized (this) {  
  13.             int i=0;  
  14.             while(i++ < 3){  
  15.                 System.out.println(Thread.currentThread().getName() +":"+ i);  
  16.                 try {  
  17.                     Thread.sleep(1000);  
  18.                 } catch (InterruptedException e) {  
  19.                     e.printStackTrace();  
  20.                 }  
  21.             }  
  22.         }  
  23.     }  
  24.       
  25.     public void method02(){  
  26.           
  27.         //第1种方式:当一个线程访问object的一个synchronized(this)同步代码块时,  
  28.         //另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  
  29. //      int j=0;  
  30. //      while(j++ < 3){  
  31. //          System.out.println(Thread.currentThread().getName() +":"+ j);  
  32. //          try {  
  33. //              Thread.sleep(1000);  
  34. //          } catch (InterruptedException e) {  
  35. //              e.printStackTrace();  
  36. //          }  
  37. //      }  
  38.           
  39.         //第2种方式:当一个线程访问object的一个synchronized(this)同步代码块时,  
  40.         //其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。  
  41.         synchronized (this) {  
  42.             int j=0;  
  43.             while(j++ < 3){  
  44.                 System.out.println(Thread.currentThread().getName() +":"+ j);  
  45.                 try {  
  46.                     Thread.sleep(1000);  
  47.                 } catch (InterruptedException e) {  
  48.                     e.printStackTrace();  
  49.                 }  
  50.             }  
  51.         }  
  52.     }  
  53.       
  54.     /**  
  55.      * 当一个线程访问object的一个synchronized(this)同步代码块时,  
  56.      * 它就获得了这个object的对象锁。  
  57.      * 结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。  
  58.      */  
  59.     public synchronized void method3(){  
  60.         int k=0;  
  61.         while(k++ < 3){  
  62.             System.out.println(Thread.currentThread().getName() +":"+ k);  
  63.             try {  
  64.                 Thread.sleep(1000);  
  65.             } catch (InterruptedException e) {  
  66.                 e.printStackTrace();  
  67.             }  
  68.         }  
  69.     }  
  70.       
  71.     public static void main(String[] args) {  
  72.         final Thread02 t02 = new Thread02();  
  73.           
  74.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  75.                   +"synchronized 关键字使用 \n"  
  76.                   +"--------------------------");  
  77.           
  78.         Thread t02A = new Thread(new Runnable() {  
  79.               
  80.             @Override  
  81.             public void run() {  
  82.                 t02.method01();  
  83.             }  
  84.         },"A");  
  85.           
  86.         Thread t02B = new Thread(new Runnable() {  
  87.               
  88.             @Override  
  89.             public void run() {  
  90.                 t02.method02();  
  91.             }  
  92.         },"B");  
  93.           
  94.         Thread t02C = new Thread(new Runnable() {  
  95.               
  96.             @Override  
  97.             public void run() {  
  98.                 t02.method3();  
  99.             }  
  100.         },"C");  
  101.           
  102.         t02A.start();  
  103.         t02B.start();  
  104.         t02C.start();  
  105.     }  
  106.   
  107. }  
运行结果如下:

[html] view plaincopy
  1. Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. B:1  
  5. B:2  
  6. B:3  
  7. C:1  
  8. C:2  
  9. C:3  
  10. A:1  
  11. A:2  
  12. A:3  


【3】synchronized  Demo3:

[html] view plaincopy
  1. package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * synchronized对象锁  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public class Thread03 {  
  9.       
  10.     class InnerObject{  
  11.           
  12.         /**  
  13.          * 内部类方法1  
  14.          */  
  15.         private void innerMethod01(){  
  16.             int i=0;  
  17.             while(i++ < 3){  
  18.                 System.out.println(Thread.currentThread().getName() +":"+ i);  
  19.                 try {  
  20.                     Thread.sleep(1000);  
  21.                 } catch (InterruptedException e) {  
  22.                     e.printStackTrace();  
  23.                 }  
  24.             }  
  25.         }  
  26.           
  27.         /**  
  28.          * 内部类方法2  
  29.          */  
  30.         private void innerMethod02(){  
  31.             int j=0;  
  32.             while(j++ < 3){  
  33.                 System.out.println(Thread.currentThread().getName() +":"+ j);  
  34.                 try {  
  35.                     Thread.sleep(1000);  
  36.                 } catch (InterruptedException e) {  
  37.                     e.printStackTrace();  
  38.                 }  
  39.             }  
  40.         }  
  41.     }  
  42.       
  43.     /**  
  44.      * 外部类方法1  
  45.      * @param innerObj  
  46.      */  
  47.     private void outerMethod01(InnerObject innerObj){  
  48.         synchronized (innerObj) {  
  49.             innerObj.innerMethod01();  
  50.         }  
  51.     }  
  52.       
  53.     /**  
  54.      * 外部类方法2  
  55.      * @param innerObj  
  56.      */  
  57.     private void outerMethod02(InnerObject innerObj){  
  58.         innerObj.innerMethod02();  
  59.     }  
  60.       
  61.     public static void main(String[] args) {  
  62.         final Thread03 t03 = new Thread03();  
  63.         final InnerObject innerObj = t03.new InnerObject();  
  64.           
  65.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  66.                           +"synchronized 关键字使用 \n"  
  67.                           +"--------------------------");  
  68.   
  69.         Thread t03A = new Thread(new Runnable() {  
  70.               
  71.             @Override  
  72.             public void run() {  
  73.                 t03.outerMethod01(innerObj);  
  74.             }  
  75.         },"A");  
  76.           
  77.         Thread t03B = new Thread(new Runnable() {  
  78.               
  79.             @Override  
  80.             public void run() {  
  81.                 t03.outerMethod02(innerObj);  
  82.             }  
  83.         },"B");  
  84.           
  85.         t03A.start();  
  86.         t03B.start();  
  87.     }  
  88.   
  89. }  
运行结果如下:

[html] view plaincopy
  1. Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. A:1  
  5. B:1  
  6. B:2  
  7. A:2  
  8. B:3  
  9. A:3  

 Synchronized 锁定的是 类变量 ,即static 变量(可能是属性,可能是方法)(锁定类对象)

Java代码

  1. public class Demo3 {     
  2.     static Object o = new Object();     
  3.     
  4.     public static synchronized void m1() {     
  5.         //....     
  6.     }     
  7.     
  8.     public static void m2() {     
  9.         //...     
  10.         synchronized (Demo3.class) {     
  11.             //.....     
  12.         }     
  13.         //.....     
  14.     }     
  15.     
  16.     public static void m3() {     
  17.         //..........     
  18.         try {     
  19.             synchronized (Class.forName("Demo3")) {     
  20.               //............     
  21.             }     
  22.         } catch (ClassNotFoundException ex) {     
  23.         }     
  24.         //.............     
  25.     }     
  26.     
  27.     public static void m4() {     
  28.         //............     
  29.        synchronized(o){     
  30.          //........     
  31.        }     
  32.         //..........     
  33.     }     
  34. }    

以上4个方法中实现的效果都是一样的,其锁定的对象都是类Demo3,而不是类实例对象 ,即在多线程中,其共享的资源是属于类的,而不是属于类对象的。在这种情况下,如果thread1 访问了这4个方法中的任何一个, 在同一时间内其它的线程都不能访问 这4个方法。


总结:

1.  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。  

2. synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。  

对synchronized(this)的一些理解 
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。  

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。  

四、当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞

原创粉丝点击