java高并发锁,java 分布式锁与并发锁

  java高并发锁,java 分布式锁与并发锁

  00-1010一、相似点:锁vs同步代码块二。锁接口III中的方法。区别:锁与同步代码块IV。锁4.1重入。重新进入同步锁4.2。可重入锁的重入与锁的公平性

  

目录

Lock lock是一种类似于同步代码块的线程同步机制。从Java 5开始,java.util.concurrent.Locks引入了几个锁的实现类,所以我们通常不需要实现自己的锁。知道如何使用它们并理解它们实现背后的原理是很重要的。

 

  Lock API的基本用法类似于Synchronized关键字,代码如下

  lock lock=new reentrant lock();//实例化锁//lock . lock();//Lock boolean locked=Lock . try Lock();//Try lock if(locked){ Try {//locked同步代码块,同一时间只能有一个线程执行} finally { lock . unlock();//放在一个finally代码块中,保证锁会被释放}}synchronized(obj){ //一个被锁定的同步代码块,同一时间只能被一个线程执行}使用锁锁看起来比较麻烦,但是java默认提供了很多锁锁,可以满足更多的应用场景。例如:基于信号量的锁定、读写锁定等。关注我的专栏《java并发编程》,后面会介绍。

  

一、相似之处:Lock锁 vs Synchronized 代码块

锁接口实现方法通常维护一个计数器。当计数器=0时,资源被释放,当计数器大于1时,资源被锁定。

 

  公共接口锁{ void Lock();void lockInterruptibly()引发InterruptedException布尔tryLock();布尔tryLock(long time,TimeUnit单位)抛出InterruptedExceptionvoid unlock();condition new condition();} lock()-调用这个方法会将锁计数器加1。如果共享资源此时处于空闲状态,锁将被授予调用该方法的线程。unlock()-调用此方法将锁计数器减1。当锁计数器为0时,资源被释放。try lock()-如果资源空闲,那么调用这个方法将返回true,锁计数器将增加1。如果资源被占用,该方法返回false,但线程不会被阻塞。Trylock(长超时,时间单位单位)——尝试按照这个方法获取一个锁。如果此时资源被占用,线程将在退出前等待一段时间。这段时间由该方法的参数定义,以便期望在这段时间内获得资源锁。lock interruptible()-如果资源空闲,该方法将获取锁,同时允许线程在获取资源时被其他线程中断。这意味着,如果当前线程正在等待锁,但其他线程要求获取锁,那么当前线程将被中断,并将立即返回,而不获取锁。

  00-1010使用synchronized同步块和使用Lock API之间仍有一些区别。

  同步的同步块必须完全包含在一个方法中——但是lock API的Lock()和unlock()操作可以在不同的方法中执行。synchronized同步块不支持公平原则,任何线程都可以在释放后重新获得锁,并且不能指定优先级。但是,我们可以通过指定fair属性在锁API中实现公平优先级,这样等待时间最长的线程就可以获得锁。如果一个线程不能访问同步的同步块,它将被阻塞并等待。Lock API提供tryLock()方法,该方法尝试获取锁对象,如果获取了锁则返回true,否则返回false。True返回不会阻塞线程,因此使用此方法可以减少等待锁的线程的阻塞时间。

  00-1010“可重入”是指一个线程可以多次安全地获取同一个锁对象而不会死锁。

  00-1010以下同步代码块嵌套同步代码块,锁定同一个this对象,不会发生死锁。证明了同步的代码块锁同一个对象,并且是可重入的。

  p>

public void testLock(){ synchronized (this) { System.out.println("第1次获取锁,锁对象是:" + this); int index = 1; do { synchronized (this) { System.out.println("第" + (++index) + "次获取锁,锁对象是:" + this); } } while (index != 10); }}

上面的这段代码输出结果是

 

  

第1次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第2次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第3次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第4次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第5次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第6次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第7次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第8次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第9次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116第10次获取锁,锁对象是:com.example.demo.thread.TestLockReentrant@769c9116

 

  

4.2.ReentrantLock可重入锁

Lock接口的实现类ReentrantLock,也是可重入锁。一般来说类名包含Reentrant的Lock接口实现类实现的锁都是可重入的。

 

  

public void testLock1(){ Lock lock = new ReentrantLock(); //实例化锁 lock.lock(); //上锁 System.out.println("第1次获取锁,锁对象是:" + lock); try { int index = 1; do { lock.lock(); //上锁 try { System.out.println("第" + (++index) + "次获取锁,锁对象是:" + lock); }finally { lock.unlock(); } } while (index != 10); }finally { lock.unlock(); //放在finally代码块中,保证锁一定会被释放 }}

当线程第一次获得锁的时候,计数器被设置为1。在解锁之前,该线程可以再次获得锁,每次计数器都会增加1。对于每一个解锁操作,计数器被递减1,当计数器为0时锁定资源被释放。所以最重要的是:lock(tryLock)要与unlock方法成对出现,即:在代码中加锁一次就必须解锁一次,否则就死锁

 

  

 

  

五、Lock锁的公平性

Java的synchronized 同步块对试图进入它们的线程,被授予访问权(占有权)的优先级顺序没有任何保证。因此如果许多线程不断争夺对同一个synchronized 同步块的访问权,就有可能有一个或多个线程从未被授予访问权。这就造成了所谓的 "线程饥饿"。为了避免这种情况,锁应该是公平的。

 

  

Lock lock = new ReentrantLock(true);

可重入锁提供了一个公平性参数fairness ,通过该参数Lock锁将遵守锁请求的顺序,即在一个线程解锁资源后,锁将被交给等待时间最长的线程。这种公平模式是通过在锁的构造函数中传递 "true "来设置的。

 

  以上就是java并发编程Lock锁可重入性与公平性分析的详细内容,更多关于并发Lock锁可重入性公平性的资料请关注盛行IT其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: