Java中lock和synchronized的用法

今天做笔试的时候要写一个同步代码,忽然发现对synchronized和lock的使用不是很熟练,查阅了相关资料,练习了几个例子,对这两个的基本用法熟悉了,在这里记录下。
一、synchronized有四种用法,分别如下:
1、直接修饰实例方法,这时候锁住的是该方法所在的对象,想执行demo1.consumer()方法时必须先获得Demo类的实例对象demo1的锁。因此进行线程同步的时候必须确保要同步的线程调用的都是同一个对象的consumer()方法,因为每个对象都有一把锁,调用demo1.consumer()方法不需要获得demo2对象的锁,即调用demo1.consumer()和demo2.consumer()分别需要demo1和demo2的对象锁。

	public class Demo{
		private static int number = 10000;
		synchronized void consumer() {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

2、直接修饰静态方法,这时候锁住的是该方法所在的类,即所有该类的所有对象拥有同一个锁,调用Demo.consumer()方法时需获取该类的锁,如果采用实例对象来调用,即调用demo1.consumer()和demo2.consumer()需要获取的是同一个对象锁,需要同步的两个线程分别调用demo1.consumer()和demo2.consumer()可实现同步。

	public class Demo{
		private static int number = 10000;
		synchronized void consumer() {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

3、直接修饰你想锁住的实例对象,如下面的demo跟第一种情况是等价的,synchronized (this)即锁住了Demo类的实例对象。

public class Demo{	
	static private int number = 10000; 
	void consumer() {	
		synchronized (this) {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    }
		}
	}
}
	

4、直接修饰你想锁住的类(可以用于静态方法和实例方法),如下面举的例子跟第二个例子是等价的,即锁住了该类全部的实例对象。

public class Demo{	
	static private int number = 10000; 
	void consumer() {	
		synchronized (Demo.class) {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    }
		}
	}
}

二、lock的基本用法如下,其中lock是一个Lock类的实例对象(一般是Lock lock = new ReentrantLock()),如果lock是静态变量(用static修饰),那么使用下面用法锁住的就是lock所属的类,如果lock是实例变量(没用static修饰),那么使用下面用法锁住的就是lock所属的类的实例对象,举例如下:

		lock.lock();
			try {
	
			}  finally {
				lock.unlock();
			}

1、实例变量(不用static修饰),该例子效果与synchronized的第三种情况等价。

public class Demo{	
	static private int number = 10000;
	private Lock lock = new ReentrantLock(); 
	void consumer() {	
		this.lock.lock();
		try {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    }
		}finally{
			this.lock.unlock();
		}
	}
}

2、静态变量(用static修饰),该例子效果与synchronized的第四种情况等价。

public class Demo{	
	static private int number = 10000;
	private static Lock lock = new ReentrantLock(); 
	void consumer() {	
		lock.lock();
		try {
			if (number > 0) {
				int num = number;
				int x = num;
				num = num - (int) (Math.random() * 400) - 100;
				if (num < 0)
					num = 0;
				else 
					x = x - num;
				number = num;
				System.out.println("贷款了" + x + "元");
				System.out.println("剩余" + num + "元");
				if (num == 0)
					System.out.println("贷款结束了");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    }
		}finally{
			lock.unlock();
		}
	}
}

三、本人测试过synchronized和lock无法同时使用,它们同时锁住同一个对象时无法实现同步的效果,我觉得应该是两种锁机制的实现方式不同而导致的。synchronized是采用JVM来进行同步,而Lock采用AQS同步框架和naive方法通过内核来实现同步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值