1. 程式人生 > >Java的類鎖和物件鎖

Java的類鎖和物件鎖

類鎖和物件鎖不是同1個東西,一個是類的Class(對應的唯一的一個即這類的二進位制位元組碼)物件的鎖,1個是類的例項(!即new出的一個類的物件,一個類會有多個例項物件)的鎖。也就是說:1個執行緒訪問靜態synchronized的時候,允許另一個執行緒訪問物件的例項synchronized方法。反過來也是成立的,因為他們需要的鎖是不同的。

物件鎖:java的所有物件(即new出的一個類的物件,一個類會有多個例項物件)都含有1個互斥鎖,這個鎖由JVM自動獲取和釋放。執行緒進入synchronized方法的時候獲取該物件的鎖,當然如果已經有執行緒獲取了這個物件的鎖,那麼當前執行緒會等待;synchronized方法正常返回或者拋異常而終止,JVM會自動釋放物件鎖。這裡也體現了用synchronized來加鎖的1個好處,方法拋異常的時候,鎖仍然可以由JVM來自動釋放。

類鎖:物件鎖是用來控制例項方法之間的同步,類鎖是用來控制靜態方法(或靜態變數互斥體)之間的同步。其實類鎖只是一個概念上的東西,並不是真實存在的,它只是用來幫助我們理解鎖定例項方法和靜態方法的區別的我們都知道,java類可能會有很多個物件,但是隻有1個Class物件,也就是說類的不同例項之間共享該類的Class物件。Class物件其實也僅僅是1個java物件,只不過有點特殊而已。由於每個java物件都有1個互斥鎖,而類的靜態方法是需要Class物件所以所謂的類鎖,不過是Class物件的鎖而已。獲取類的Class物件有好幾種,最簡單的就是MyClass.class的方式。

/**
 * 
 */

/**
 * 物件鎖和類鎖的使用
 * <p>Title: MyTest</p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author 夏 傑
 * @date 2015年12月17日 下午10:45:15
 * @vesion 1.0
*/
public class MyLock {
	
	/**
	 *  物件鎖:形式1
	 *  synchroined 修飾方法 直接方法名,對應的是當前類的new出來物件例項的例項碩
	 */
	public synchronized void objLockMethod1()
	{
		System.out.println("in...objLockMethod1");
		try
		{
			Thread.sleep(500);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		System.out.println("out...objLockMethod1");
	}

	
	    /**
	     * 物件鎖:形式2
	     * synchonced(this) 修飾程式碼塊 ,this代表的是當前類的例項物件鎖
	     */
		public void objLockMethod2()
		{
			synchronized (this)
			{
				System.out.println("in...objLockMethod2");
				try
				{
					Thread.sleep(500);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				System.out.println("out...objLockMethod2");
			}

		}
	

		/**
		 * 類鎖:形式1
		 * static 類 用synchronized修飾 對應的是該類對應的Class類物件,只有唯一的一個
		 */
		public static synchronized void classLock1()
		{
			System.out.println("classLock1------in");
			try
			{
				Thread.sleep(500);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			System.out.println("classLock1------out");
		}
		
		
		/**
		 * 類鎖:形式2
		 * synchronized (MyLock.class) 
		 * synchronized中的鎖使用 本類名.class 對應的是該類對應的Class類物件,只有唯一的一個
		 */
		public static  void classLock2()
		{
			synchronized (MyTest.class) {
				System.out.println("classLock2------in");
				try
				{
					Thread.sleep(500);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				System.out.println("classLock2------out");
			}
			
		}
	

}

物件鎖和類鎖的測試
/**
 * 
 */

/**
 * <p>Title: Thread1</p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author 夏 傑
 * @date 2015年12月17日 下午11:20:40
 * @vesion 1.0
*/
public class Thread1 implements Runnable{
	
	MyLock myLock ;

	public Thread1(MyLock myLock) {
		this.myLock = myLock;
	}

	
	@Override
	public void run() {
		
		myLock.classLock1();
	}

}

/**
 * 
 */

/**
 * <p>Title: Thread1</p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author 夏 傑
 * @date 2015年12月17日 下午11:20:40
 * @vesion 1.0
*/
public class Thread2 implements Runnable{
	
	MyLock myLock ;

	public Thread2(MyLock myLock) {
		this.myLock = myLock;
	}

	@Override
	public void run() {
		
		myLock.objLockMethod1();
	}

}
/**
 * 
 */

/**
 * <p>Title: ThreadMain</p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author 夏 傑
 * @date 2015年12月17日 下午11:27:05
 * @vesion 1.0
*/
public class ThreadMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
	  MyLock myLock = new MyLock();
	  new Thread(new Thread1(myLock)).start();
	  new Thread(new Thread2(myLock)).start();
	  
	}

}


    可以看出,類鎖和物件鎖不是同1個東西,一個是類的Class物件的鎖,1個是類的例項的鎖。也就是說:1個執行緒訪問靜態synchronized的時候,允許另一個執行緒訪問物件的例項synchronized方法。反過來也是成立的,因為他們需要的鎖是不同的。