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方法。反过来也是成立的,因为他们需要的锁是不同的。





    原文作者:java锁
    原文地址: https://blog.csdn.net/zuoanyinxiang/article/details/50347619
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞