1.方法聲明時使用,放在範圍操作符(public等)之後,返回類型聲明(void等)之前.這時,線程獲得的是成員鎖,即一次只能有一個線程進入該方法,其他線程要想在此時調用該方法,只能排隊等候,當前線程(就是在synchronized方法內部的線程)執行完該方法後,別的線程才能進入.例如:
public synchronized void synMethod() {
//方法體
}
2.對某一代碼塊使用,synchronized後跟括號,括號裏是變量,這樣,一次只有一個線程進入該代碼塊.此時,線程獲得的是成員鎖.例如:
public int synMethod(int a1){
synchronized(a1) {
//一次只能有一個線程進入
}
}
3.synchronized後面括號裏是一對象,此時,線程獲得的是對象鎖.例如:
public class MyThread implements Runnable {
public static void main(String args[]) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt, "t1");
Thread t2 = new Thread(mt, "t2");
Thread t3 = new Thread(mt, "t3");
t1.start();
t2.start();
t3.start();
}
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
}
}
對於3,如果線程進入,則得到當前對象鎖,那麼別的線程在該類所有對象上的任何操作都不能進行.在對象級使用鎖通常是一種比較粗糙的方法。爲什麼要將整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只爲了讓一個線程使用其中一部分資源,就將所有線程都鎖在外面。由於每個對象都有鎖,可以如下所示使用虛擬對象來上鎖:
class FineGrainLock {
MyMemberClass x, y;
Object xlock = new Object(), ylock = new Object();
public void foo() {
synchronized(xlock) {
//access x here
}
//do something here - but don't use shared resources
synchronized(ylock) {
//access y here
}
}
public void bar() {
synchronized(this) {
//access both x and y here
}
//do something here - but don't use shared resources
}
}
4.synchronized後面括號裏是類,此時,線程獲得的是對象鎖.例如:
class ArrayWithLockOrder{
private static long num_locks = 0;
private long lock_order;
private int[] arr;
public ArrayWithLockOrder(int[] a)
{
arr = a;
synchronized(ArrayWithLockOrder.class) {//-----這裏
num_locks++; // 鎖數加 1。
lock_order = num_locks; // 爲此對象實例設置唯一的 lock_order。
}
}
public long lockOrder()
{
return lock_order;
}
public int[] array()
{
return arr;
}
}
class SomeClass implements Runnable
{
public int sumArrays(ArrayWithLockOrder a1,
ArrayWithLockOrder a2)
{
int value = 0;
ArrayWithLockOrder first = a1; // 保留數組引用的一個
ArrayWithLockOrder last = a2; // 本地副本。
int size = a1.array().length;
if (size == a2.array().length)
{
if (a1.lockOrder() > a2.lockOrder()) // 確定並設置對象的鎖定
{ // 順序。
first = a2;
last = a1;
}
synchronized(first) { // 按正確的順序鎖定對象。
synchronized(last) {
int[] arr1 = a1.array();
int[] arr2 = a2.array();
for (int i=0; i<size; i++)
value += arr1[i] + arr2[i];
}
}
}
return value;
}
public void run() {
//
}
}
對於4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對於含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖.