java 同步塊(Java Synchronized Blocks)

Java 同步塊包括方法同步和代碼塊同步。java 同步能夠避免資源競爭,避免死鎖。html

主題包括的主要內容:java

The Java synchronized Keyword

在java中,同步是用 synchronized 關鍵字表明的. 同步是針對對象和類來講的。一個對象上的全部同步塊只能被一個線程鎖住。其餘全部的線程試圖訪問同步塊的方法,都要等到佔用資源的線程釋放了才能訪問。orm

synchronized關鍵字能夠用到4個種場景:htm

  1. Instance methods

  2. Static methods

  3. Code blocks inside instance methods

  4. Code blocks inside static methods

Synchronized Instance Methods

Here is a synchronized instance method:

  public synchronized void add(int value){
      this.count += value;
  }

當一個方法上用到synchronized關鍵字,Java才能知道它是個同步方法。

一個實例同步方法只屬於實例自己。每一個實例都有本身的同步方法。

Synchronized Static Methods

Static methods are marked as synchronized just like instance methods using thesynchronized keyword. Here is a Java synchronized static method example:

  public static synchronized void add(int value){
      count += value;
  }

一樣 synchronized 告訴Java 這是一個同步方法。

同步靜態方法屬於類對象。在VM中只有一個類對象,所以只能有一個線程執行靜態同步方法。

Synchronized Blocks in Instance Methods

有時候, 不須要同步整個方法,只須要同步方法裏面的一部分,能夠藉助同步塊來完成工做。

Here is a synchronized block of Java code inside an unsynchronized Java method:

  public void add(int value){    synchronized(this){
       this.count += value;   
    }
  }

這個例子是用同步塊標記一塊同步代碼。這個同步塊代碼就至關於同步方法。

Notice how the Java synchronized block construct takes an object in parentheses. In the example "this" is used, which is the instance the add method is called on. The object taken in the parentheses by the synchronized construct is called a monitor object. The code is said to be synchronized on the monitor object. A synchronized instance method uses the object it belongs to as monitor object.

對於同一個對象只能有一個線程訪問同步塊。

下面兩個方法的代碼,效果是同樣的。

 
  public class MyClass {
  
    public synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public void log2(String msg1, String msg2){       synchronized(this){
          log.writeln(msg1);
          log.writeln(msg2);       }
    }
  }

只能有一個線程執行(針對同一個對象) ;

第二個方法是不一樣的線程執行的時候會在同步塊裏面發生等待(針對同一對象)。

Synchronized Blocks in Static Methods

下面兩個靜態方法是在類對象上的:

  public class MyClass {

    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);  
       }
    }
  }

一個線程只能在同一時間執行上面的任何一個方法。

對於第二個方法:只能有一個線程在代碼塊裏面執行。

Java Synchronized Example


  public class MyClass {


    public static synchronized void log1(String msg1, String msg2){	 try {	    	    TimeUnit.SECONDS.sleep(5) ;	    	} catch (InterruptedException e) {	    	    e.printStackTrace();	    	}
       System.out.println(msg1);
       System.out.println(msg2);
    }
    
    public static synchronized void log3(String msg1, String msg2){	    System.out.println(msg1);	    System.out.println(msg2);  
    }
  
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){	   try {	    	    TimeUnit.SECONDS.sleep(3) ;	    	} catch (InterruptedException e) {	    	    e.printStackTrace();	    	}	   System.out.println(msg1);	   System.out.println(msg2);  
       }
    }
    
    public static void log4(String msg1, String msg2){	synchronized(MyClass.class){	    	    System.out.println(msg1);	    System.out.println(msg2);  	}
    }
    
   
    public void log5(String msg1, String msg2){	synchronized(this){	    System.out.println(msg1);	    System.out.println(msg2);  	}
    }
    
  }
  public class SynchronizedTest {


    Thread t1 = new Thread(new Runnable() {
        
        @Override
        public void run() {
          
            MyClass.log1("msg11", "msg12") ;
        }
    }) ;
    Thread t2 = new Thread(new Runnable() {
        
        @Override
        public void run() {
           
            MyClass.log2("msg21", "msg22") ;
        }
    }) ;
    Thread t3 = new Thread(new Runnable() {		@Override	public void run() {	    	    MyClass.log3("msg31", "msg32") ;	}
    }) ;
    
    Thread t4 = new Thread(new Runnable() {		@Override	public void run() {	    	    MyClass.log4("msg41", "msg42") ;	}
    }) ;
    
    Thread t5 = new Thread(new Runnable() {		@Override	public void run() {	    	   new  MyClass().log5("msg51", "msg52") ;	}
    }) ;
    
    public static void main(String[] args) {	SynchronizedTest st = new SynchronizedTest() ;		st.t1.start() ;
//	st.t3.start() ;	//	st.t2.start() ;
//	st.t4.start() ;	st.t5.start() ;			 int i = 0 ;		while(true){		    try {			TimeUnit.SECONDS.sleep(1) ;			System.out.println("---------------> " + i);			i ++ ;					    } catch (InterruptedException e) {			e.printStackTrace();		    }		    if(i > 10 ){			    break ;		    }		}				    }
    
}

測試組合:

1. 測試實例方法組合;

2. 測試靜態方法組合;

3. 測試實例方法和靜態方法組合;(注意方法裏面的 sleep, 是爲了作到更好的測試效果)。

相關文章
相關標籤/搜索