Java多線程學習篇(二)synchronized
阿新 • • 發佈:2018-01-03
參考 .get name syn his col 靜態方法 runtest 作用範圍
synchronized 有二種修飾方法:
-
修飾一個方法
synchronized public void runTest{ /**/ }
-
修飾一個代碼塊
public void runTest{ synchronized( /*某一對象或某一類*/ ){ /* 代碼塊 */ } }
synchronized 的作用範圍分為修飾一個類和修飾一共對象
當修飾一個對象時,不同線程的同一對象調用相同代碼會發生堵塞
當修飾一個類時,不同線程的同一類調用相同代碼會發生堵塞
修飾靜態方法相當於修飾類
定義一個類(用於驗證 synchronized 的作用範圍)
publicclass Test implements Runnable { public static int Count = 0; @Override public void run() { runTest(); } public void runTest() { for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
當 synchronized 修飾一個方法時
-
若方法為非靜態方法,作用的範圍是一個對象
不同線程的同一對象調用該方法時會發生堵塞
//調用相同的對象
synchronized public void runTest() { // 修飾非靜態的方法 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } }通過以下代碼調用
Test test = new Test(); Thread thread_one
結果是
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
由於該調用是二個thread任務中的對象是同一個test,第一個thread任務運行時,會將第二個任務堵塞
若對象不是同一個,則不會發生堵塞
//調用二個不同的對象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start();
結果是
Thread_Two 2 Thread_ONE 1 Thread_Two 3 Thread_ONE 4 Thread_Two 5 Thread_ONE 6 Thread_Two 7 Thread_ONE 8 Thread_Two 9 Thread_ONE 10
-
當修飾的方法為靜態的方法時,作用的範圍是一個類,而非一個對象。
不同線程的相同類調用該方法時都會發生堵塞
//調用相同的對象 Test test = new Test(); Thread thread_one = new Thread( test, "Thread_ONE" ); Thread thread_two = new Thread( test, "Thread_Two" ); thread_one.start(); thread_two.start(); //調用二個不同的對象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start();
結果都為
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
當 synchronized 修飾一個代碼塊時,作用的範圍看括號內的內容。若括號內為對象,則範圍是一個對象;若括號內為類,則範圍是一個類
-
若括號內為對象,則範圍是一個對象,效果和 synchronized 修飾非靜態方法一樣
public void runTest() { synchronized (this) { // 括號內為一個對象 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
效果
//調用相同的對象 Test test = new Test(); Thread thread_one = new Thread( test, "Thread_ONE" ); Thread thread_two = new Thread( test, "Thread_Two" ); thread_one.start(); thread_two.start(); //發生類堵塞 //Thread_ONE 1 //Thread_ONE 2 //Thread_ONE 3 //Thread_ONE 4 //Thread_ONE 5 //Thread_Two 6 //Thread_Two 7 //Thread_Two 8 //Thread_Two 9 //Thread_Two 10 //調用二個不同的對象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start(); // 沒有發生堵塞 //Thread_Two 2 //Thread_ONE 1 //Thread_Two 3 //Thread_ONE 4 //Thread_Two 5 //Thread_ONE 6 //Thread_Two 7 //Thread_ONE 8 //Thread_Two 9 //Thread_ONE 10
-
若括號內為類,則範圍是一個對象,效果和 synchronized 修飾靜態方法一樣
public [static] void runTest() { synchronized (Test.class) { // 括號內為一個類 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
二種調用都發生堵塞
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
參考:http://tutorials.jenkov.com/java-concurrency/synchronized.html
Java多線程學習篇(二)synchronized