Java線程_類鎖(靜態鎖)的實現及討論

首先什麼是類鎖?

就像可以對類的每一個實例(對象)獲取一個對象鎖一樣,對於每一個類都可以獲取一個鎖,我們稱之爲類鎖。

然後爲什麼要有靜態鎖?

簡而言之,一個非靜態方法獲取靜態鎖通常是爲了在防止靜態數據上發生競態條件。因爲靜態方法是屬於類的,即對於靜態方法而言是沒有對象引用的概念的,那麼此時就無法使用對象來對靜態方法進行鎖定了。我們可以做這樣的考慮,就是既然靜態方法是屬於類的,那麼我們是否可以使用類對象來做鎖定依據呢?答案是肯定的,我們可以使用表示當前類的類對象或者從屬於當前類靜態域的靜態對象來做鎖的判斷依據。

使用方法

一個簡單的例子,對比使用了靜態鎖和沒使用了靜態鎖的兩種情況

package com.wly.javathread.chap3;

/**
 * 測試靜態鎖(類鎖)的使用
 * 靜態鎖(類鎖)主要用來防止在靜態數據上發生競態條件,理論依據是要操作靜態數據必須先獲取到靜態鎖(類鎖)的原理
 * @author wly
 *
 */
public class TestStaticLock {

	static Score2 score2;
	static Score1 score1;
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		//測試沒有加靜態鎖的情況
		System.out.println("--測試沒有加靜態鎖的情況--");
		Thread[] threads = new Thread[1000];
		for(int j=0;j<10;j++) { //循環測試多次
			score1 = new Score1();
			for(int i=0;i<threads.length;i++) {
				threads[i] = new Thread() {

					@Override
					public void run() {
						super.run();
						score1.add(10);
						try {
							this.sleep(3);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						score1.deduct(10);
					}
				};
				threads[i].start();
			}
			//等待所有線程都結束
			for(int i=0;i<threads.length;i++) {
				try {
					threads[i].join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			score1.printScore();
		}
		
		//測試加了靜態鎖的情況
		System.out.println("--測試加了靜態鎖的情況--");
		for(int j=0;j<10;j++) { //循環測試多次
			score2 = new Score2();
			for(int i=0;i<threads.length;i++) {
				threads[i] = new Thread() {

					@Override
					public void run() {
						super.run();
						score2.add(10);
						try {
							this.sleep(3);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						score2.deduct(10);
					}
				};
				threads[i].start();
			}
			//等待所有線程都結束
			for(int i=0;i<threads.length;i++) {
				try {
					threads[i].join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			score2.printScore();
		}
	}	
}

/**
 * 沒有加靜態鎖的實現
 * @author wly
 *
 */
class Score1 {
	static int score;
	
	public void add(int num) {
		score += num;
	}
	
	public void deduct(int num) {
		score -= num;
	}

	public void printScore() {
		System.out.println("score:" + score);
	}
}


/**
 * 加了靜態鎖的實現
 * @author wly
 *
 */
class Score2 {
	static int score;
	
	public void add(int num) {
		synchronized (Score2.class) {
			score += num;
		}
	}
	
	public void deduct(int num) {
		synchronized (Score2.class) {
			score -= num;
		}
	}

	public void printScore() {
		System.out.println("score:" + score);
	}
}

運行結果:

--測試沒有加靜態鎖的情況--
score:10
score:10
score:10
score:10
score:20
score:10
score:10
score:10
score:10
score:10
--測試加了靜態鎖的情況--
score:0
score:0
score:0
score:0
score:0
score:0
score:0
score:0
score:0
score:0

類鎖和對象鎖
類鎖和對象鎖是兩種不同的鎖,如果一個非靜態同步方法調用了一個靜態同步方法,它就擁有了兩個不同的鎖。因爲一個靜態同步方法在沒有對象引用的情況下不調用能非靜態同步方法,所以這兩種同步方法發生死鎖的概率很小。

其他鎖定方式

a.使用其他靜態對象做鎖定依據

public class Test {
    private static int count = 0;
    private static final Object countLock = new Object();

    public void incrementCount() {
        synchronized (countLock) {
            count++;
        }
    }
} 

b.在靜態方法上使用synchronized修飾符

public class Test {
    private static int count = 0;

    public static synchronized void incrementCount() {
        count++;
    }
} 

O啦~~~

裝載請保留出處:http://blog.csdn.net/u011638883/article/details/18040949

謝謝!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章