這裡通過三個測試類闡述了synchronized應用的不同場景
首先是最基本的synchronized Method的使用
- package com.jadyer.thread.sync;
-
- /**
- * Synchronized Method Test
- * @see ===================================================================================================
- * @see 概述:Java中的每個對象都有一個鎖(lock)或者叫做監視器(monitor)
- * @see 說明:當synchronized關鍵字修飾一個方法時,則該方法為同步方法
- * @see 當某個線程訪問某個對象的synchronized方法時,則表示將該對象上鎖
- * @see 此時其它的任何線程,均無法訪問該對象中的任何一個synchronized方法(但允許訪問該對象中的非synchronized方法)
- * @see 直到該線程所訪問的synchronized方法執行完畢(或者拋出了異常)之後,該對象的鎖才會被釋放
- * @see 此時其它的任何線程,才被允許訪問該synchronized方法,或者是該對象中的其它synchronized方法
- * @see ===================================================================================================
- * @see 總結:如果一個對象有多個synchronized方法,某一時刻某個線程已經執行了該對象中的某一個synchronized方法
- * @see 那麼在該方法沒有執行完畢之前,其它線程是無法訪問該對象中的,包括該方法在內的,任何一個synchronized方法
- * @see 重點在於判斷Synchronized鎖的是誰。如果該方法是靜態的,則鎖Class對象,否則鎖的就是當前對象
- * @see ===================================================================================================
- * @see 補充:1)這只是針對多個線程操作同一個類的同一個對象的情況。www.linuxidc.com若多個線程操作同一個類的不同對象,則不存在這種情況
- * @see 2)Java中的volatile變量也可以看作是一種"程度較輕的synchronized"
- * @see 關於volatile的更多信息,請參考http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
- * @see 備注:實際項目中,用到的更多的還是JDK5.0開始推出的Java並發包,即java.util.concurrent包裡面的工具類
- * @see java.util.concurrent可以非常細粒度的實現並發。比如線程訪問到了一個已被鎖的對象,它可以讓這個線程等到10秒
- * @see 10秒後如果該對象仍未被解鎖,那麼就可以返回給用戶超時的提示等,而如果使用synchronized則是無法這麼精確控制的
- * @see ===================================================================================================
- * @see 注意:1)當synchronized方法執行完或者發生異常時,會自動釋放鎖
- * @see 2)被synchronized保護的數據應該是private的,否則也就沒必要去通過方法來訪問這個public的數據了
- * @see ===================================================================================================
- * @author 宏宇
- * @create Feb 21, 2012 5:29:39 PM
- */
- public class SynchronizedTest {
- public static void main(String[] args) {
- Bank bank = new Bank();
-
- Thread tt11 = new Thread(new ThreadRMB(bank));
-
- //new一個新的Bank對象。此時存在兩個Bank對象,並且它們屬於同一個類的不同的對象
- //如要驗證多個線程操作同一個類的不同的對象的synchronized方法,只需取消注釋該行代碼即可
- //bank = new Bank();
-
- Thread tt22 = new Thread(new ThreadDollar(bank));
-
- tt11.start();
- tt22.start();
- }
- }
-
-
- class ThreadRMB implements Runnable{
- private Bank bank;
- public ThreadRMB(Bank bank){
- this.bank = bank;
- }
- @Override
- public void run() {
- bank.getRMB();
- }
- }
-
-
- class ThreadDollar implements Runnable{
- private Bank bank;
- public ThreadDollar(Bank bank){
- this.bank = bank;
- }
- @Override
- public void run() {
- bank.getDollar();
- }
- }
-
-
- class Bank{
- public synchronized void getRMB(){
- for(int i=0; i<20; i++){
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + ":" + i);
- }
- }
-
- public synchronized void getDollar(){
- for(int i=0; i<20; i++){
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + ":" + i);
- }
- }
- }