君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理

    Java中使用synchronized关键字来加锁达到同步的目的,synchronized可以在作用在方法上,也可以作用在代码块上。

Java中的每一个对象都可以作为锁,但是基本数量类型不行,如int、float。

 

synchronized同步非静态方法

    非静态同步方法,锁是当前对象实例,如下代码Info类中set()和get()方法都加上synchronized关键字同步,说明Info对象同一实例在同一时刻只能访问set()或get()方法:

Java代码  收藏代码
  1. public class Info {  
  2.     private String  country;  
  3.     private String  city;     
  4.     public synchronized void set(String country, String city) {  
  5.         System.out.println("进入设置方法...");  
  6.         this.country = country;  
  7.         try {  
  8.             Thread.sleep(30000);  
  9.         }  
  10.         catch (InterruptedException e) {  
  11.             e.printStackTrace();  
  12.         }  
  13.         this.city = city;  
  14.         System.out.println("完成设置...");  
  15.     }     
  16.     public synchronized void get() {  
  17.         System.out.println("进入读取方法...");  
  18.         try {  
  19.             Thread.sleep(300);  
  20.         }  
  21.         catch (InterruptedException e) {  
  22.             e.printStackTrace();  
  23.         }  
  24.         System.out.println("country:" + this.country + "->city:" + this.city);  
  25.     }     
  26.     public String getCountry() {  
  27.         return country;  
  28.     }     
  29.     public void setCountry(String country) {  
  30.         this.country = country;  
  31.     }     
  32.     public String getCity() {  
  33.         return city;  
  34.     }     
  35.     public void setCity(String city) {  
  36.         this.city = city;  
  37.     }  
  38. }  

 

synchronized同步静态方法

    同步静态方法,锁是当前类的Class对象。如Singleton单例模式在多线程下是不安全的,可以加synchronized关键字来同步,如下代码(此方法只为演示,在大多数情况下不需要同步,此方法性能不好):

Java代码  收藏代码
  1. public static synchronized Singleton getInstance() {          
  2.     if (instance == null) {  
  3.         instance = new Singleton();  
  4.     }         
  5.     return instance;  
  6. }  

 如下面测试代码,由于静态方法的锁有当前类的,所以每一个getInstance()方法都是同步的,所以性能不高:

Java代码  收藏代码
  1. /** 
  2.  * Huisou.com Inc. 
  3.  * Copyright (c) 2011-2012 All Rights Reserved. 
  4.  */  
  5.   
  6. package thread;  
  7.   
  8. import java.util.Date;  
  9.   
  10. /** 
  11.  * @description 
  12.  *  
  13.  * @author chenzehe 
  14.  * @email hljuczh@163.com 
  15.  * @create 2012-12-4 下午05:33:21 
  16.  */  
  17.   
  18. public class Singleton {  
  19.     private static Singleton    instance    = null;  
  20.       
  21.     private Singleton() {  
  22.           
  23.     }  
  24.       
  25.     public static synchronized Singleton getInstance() {  
  26.         System.out.println("...get..." + new Date());  
  27.         if (instance == null) {  
  28.             instance = new Singleton();  
  29.         }  
  30.         try {  
  31.             Thread.sleep(3000);  
  32.         }  
  33.         catch (InterruptedException e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.         System.out.println("...ret..." + new Date());  
  37.         return instance;  
  38.     }  
  39.       
  40. }  
  41.   
  42.   
  43.   
  44. /** 
  45.  * Huisou.com Inc. 
  46.  * Copyright (c) 2011-2012 All Rights Reserved. 
  47.  */  
  48.   
  49. package thread;  
  50.   
  51. import javax.xml.stream.events.StartDocument;  
  52.   
  53. /** 
  54.  * @description 
  55.  *  
  56.  * @author chenzehe 
  57.  * @email hljuczh@163.com 
  58.  * @create 2013-1-16 上午09:00:46 
  59.  */  
  60.   
  61. public class SingletonTest {  
  62.       
  63.     public static void main(String[] args) {  
  64.         new Thread() {  
  65.             public void run() {  
  66.                 System.out.println("run get...");  
  67.                 Singleton.getInstance();  
  68.             }  
  69.         }.start();  
  70.         new Thread() {  
  71.             public void run() {  
  72.                 System.out.println("run get2...");  
  73.                 Singleton.getInstance();  
  74.             }  
  75.         }.start();  
  76.     }  
  77. }  
  78.   
  79. run get...  
  80. run get2...  
  81. ...get...Wed Jan 16 09:20:12 CST 2013  
  82. ...ret...Wed Jan 16 09:20:15 CST 2013  
  83. ...get...Wed Jan 16 09:20:15 CST 2013  
  84. ...ret...Wed Jan 16 09:20:18 CST 2013  

 相对好点的多线程单例模式代码如下(懒汉模式):

Java代码  收藏代码
  1. public static Singleton getInstance() {  
  2.     if (instance == null) {  
  3.         synchronized (Singleton.class) {  
  4.             if (instance == null) {  
  5.                 instance = new Singleton();  
  6.             }  
  7.         }  
  8.     }  
  9.     return instance;  
  10. }  

 

 

synchronized关键字不能继承

      如果在父类中的某个方法使用了synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上 synchronized 关键字才可以。 还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的, 但子类调用了父类的同步方法,因此,子类的方法中调用父类方法后面的代码也就相当于同步了。

 

接口的定义不能使用 synchronized关键字

 

构造方法不能使用 synchronized关键字

 

synchronized关键字可以放在方法访问修饰前面或后面,也可以放在static前面或后面,但是只能放在返回值前面,不能放在返回值后面,如下是正确的:

public synchronized void method();

synchronized public void method();

public static synchronized void method();

public synchronized static void method();

synchronized public static void method();

下面是错误的:

public void synchronized method();

public static void synchronized method();

 

使用synchronized同步代码块

   synchronized块的语法:

Java代码  收藏代码
  1. public void method(){  
  2.     ......  
  3.     synchronized (锁对象){  
  4.         ....  
  5.     }  
  6.     ....  
  7. }  

    这样synchronized中的代码就会被加锁,锁对象为任意Java对象,对于非静态方法,锁对象一般为当前对象,可能用this关键字表示,对于内 部类,this只表示当前内部类对象,可以使用外部类.this来表示,对于静态方法,锁对象一般使用类.class来表示。

 

synchronized不能用来同步变量,如下代码是错误的:

public synchronized int i=0;

 

synchronized深入内容文章:聊聊并发(二)——Java SE1.6中的Synchronized

posted on 2013-07-23 02:07  刺猬的温驯  阅读(192)  评论(0编辑  收藏  举报