ReentrantLock与synchronized的区别

ReentrantLock和synchronized都是用来确保线程的安全性,为了在线程并发时保证线程安全,我们必须给需要进行的操作方法加“锁”。

synchronized的实现方式:

使用Synchronized关键字可以将一段代码逻辑,用一把锁给锁起来,只有获得了这把锁的线程才访问。并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住的代码,从而确保代码的线程安全。

synchronized 关键字的用法:

  • 修饰实例方法:synchronized修饰实例方法, 则用到的锁,默认为this当前方法调用对象;
  • 修饰静态方法:synchronized修饰静态方法, 则其所用的锁,默认为Class对象;
  • 修饰代码块:synchronized修饰代码块, 则其所用的锁,是某个指定Java对象;

synchronized修饰实例方法(当前对象当“锁”):

    // 递增
	public void add() {
		for (int i = 0; i < 10000; i++) {
			synchronized (this) {
				Counter1.count += 1;
			}
		}
	}

	// 递减
	public synchronized void dec() {
		for (int i = 0; i < 10000; i++) {
			Counter1.count -= 1;
		}
	}

 synchronized修饰静态方法(当前对象的class对象当“锁”):

    // 递增
	public void add() {
		for (int i = 0; i < 10000; i++) {
			synchronized (Counter2.class) {
				Counter2.count += 1;
			}
		}
	}

	// 递减
	public synchronized static void dec() {
		for (int i = 0; i < 10000; i++) {
			Counter2.count -= 1;
		}
	}

  synchronized修饰代码块(Object对象当“锁”):

//递增线程
class AddThread extends Thread{
    private static final Object lock=new Object();

	@Override
	public void run() {
		for(int i=0;i<10000;i++) {
			synchronized (lock) {
				Counter.count+=1;
			}
		}
	}
}

注意:

当一个线程访问一个对象的synchroized(this)代码块时,另一个线程仍可以访问该对象的非synchroized(this)代码块;

离开synchroized(this)代码块后,该线程所持有“锁”会自动释放。

ReentrantLock的使用:

从Java 5开始,引入了一个高级处理并发java.util.concurrent包,它提供了大量更高级的并发功能,能大大简化多线程程序的编写。

另外,ReentrantLock还有三个内部类:Sync、NonfairSync、FairSync。

  • NonfairSync 类继承了 Sync类,表示采用非公平策略获取锁:每一次都尝试获取锁,不会按照公平等待的原则进行等待,不会让等待时间最久的线程获得锁。
  • FairSync类也继承了 Sync类,表示采用公平策略获取锁:当资源空闲时,它总是会先判断 sync队列是否有等待时间更长的线程,如果存在,则将当前线程加入到等待队列的尾部,实现了公平获取原则。
  • ReentrantLock构造函数:默认是采用的非公平策略获取锁。

使用ReentrantLock代码参考如下:

class Counter {
	// 用于计数的公共变量
	public static int count = 0;
	//创建锁
	private final ReentrantLock lock = new ReentrantLock();

	// 递增
	public void add() {
		for (int i = 0; i < 10000; i++) {
			lock.lock();
			try {
				Counter.count += 1;
			} finally {
				lock.unlock();
			}
		}
	}

	// 递减
	public void dec() {
		for (int i = 0; i < 10000; i++) {
			lock.lock();
			try {
				Counter.count -= 1;
			} finally {
				lock.unlock();
			}
		}
	}
}

 ReentrantLock与synchronized的区别:

 ReentrantLocksynchronized
锁实现机制AQS监视器Monitor
获取锁可以通过tryLock()尝试获取锁,更灵活线程抢占模型
释放锁必须显示通过unlock()释放锁自动释放
锁类型支持公平锁和非公平锁非公平锁
可重入性可重入可重Rett 

ReentrantLock 区别于 synchronized来说,它不仅可以开锁关锁,它还可以尝试锁tryLock(),因此在实际的引用场景中,当产生“死锁”时,ReentrantLock可以进行一些额外处理而不是无限等待下去。所以说ReentrantLock的安全性更好一些。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值