Welcome to Java Lock example tutorial. Usually when working with multi-threaded environment, we use synchronized for thread safety.

Java Lock

Most of the times, synchronized keyword is the way to go but it has some shortcomings that lead the way to inclusion of Lock API in Java Concurrency package. Java 1.5 Concurrency API came up with java.util.concurrent.locks package with Lock interface and some implementation classes to improve the Object locking mechanism.

Some important interfaces and classes in Java Lock API are:

  1. Lock: This is the base interface for Lock API. It provides all the features of synchronized keyword with additional ways to create different Conditions for locking, providing timeout for thread to wait for lock. Some of the important methods are lock() to acquire the lock, unlock() to release the lock, tryLock() to wait for lock for a certain period of time, newCondition() to create the Condition etc.
  2. Condition: Condition objects are similar to Object wait-notify model with additional feature to create different sets of wait. A Condition object is always created by Lock object. Some of the important methods are await() that is similar to wait() and signal(), signalAll() that is similar to notify() and notifyAll() methods.
  3. ReadWriteLock: It contains a pair of associated locks, one for read-only operations and another one for writing. The read lock may be held simultaneously by multiple reader threads as long as there are no writer threads. The write lock is exclusive.
  4. ReentrantLock: This is the most widely used implementation class of Lock interface. This class implements the Lock interface in similar way as synchronized keyword. Apart from Lock interface implementation, ReentrantLock contains some utility methods to get the thread holding the lock, threads waiting to acquire the lock etc.

    synchronized block are reentrant in nature i.e if a thread has lock on the monitor object and if another synchronized block requires to have the lock on the same monitor object then thread can enter that code block. I think this is the reason for the class name to be ReentrantLock. Let’s understand this feature with a simple example.

    
    
    Copy
    public class Test{ public synchronized foo(){

    //do something

    bar();

    } public synchronized bar(){

    //do some more

    }

    }

    If a thread enters foo(), it has the lock on Test object, so when it tries to execute bar() method, the thread is allowed to execute bar() method since it’s already holding the lock on the Test object i.e same as synchronized(this).

Java Lock Example – ReentrantLock in Java

Now let’s see a simple example where we will replace synchronized keyword with Java Lock API.

Let’s say we have a Resource class with some operation where we want it to be thread-safe and some methods where thread safety is not required.


Copy
package com.journaldev.threads.lock; public class Resource {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doSomething</span>(<span class="hljs-params"></span>)</span>{
<span class="hljs-comment">//do some operation, DB read, write etc</span>
} <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doLogging</span>(<span class="hljs-params"></span>)</span>{
<span class="hljs-comment">//logging, no need for thread safety</span>
}

}

Now let’s say we have a Runnable class where we will use Resource methods.


Copy
package com.journaldev.threads.lock; public class SynchronizedLockExample implements Runnable{
<span class="hljs-keyword">private</span> Resource resource;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SynchronizedLockExample</span><span class="hljs-params">(Resource r)</span></span>{
<span class="hljs-keyword">this</span>.resource = r;
} <span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">synchronized</span> (resource) {
resource.doSomething();
}
resource.doLogging();
}

}

Notice that I am using synchronized block to acquire the lock on Resource object. We could have created a dummy object in the class and used that for locking purpose.

Now let’s see how we can use java Lock API and rewrite above program without using synchronized keyword. We will use ReentrantLock in java.


Copy
package com.journaldev.threads.lock; import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock; public class ConcurrencyLockExample implements Runnable{
<span class="hljs-keyword">private</span> Resource resource;
<span class="hljs-keyword">private</span> Lock lock; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ConcurrencyLockExample</span><span class="hljs-params">(Resource r)</span></span>{
<span class="hljs-keyword">this</span>.resource = r;
<span class="hljs-keyword">this</span>.lock = <span class="hljs-keyword">new</span> ReentrantLock();
} <span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">if</span>(lock.tryLock(<span class="hljs-number">10</span>, TimeUnit.SECONDS)){
resource.doSomething();
}
} <span class="hljs-keyword">catch</span> (InterruptedException e) {
e.printStackTrace();
}<span class="hljs-keyword">finally</span>{
<span class="hljs-comment">//release lock</span>
lock.unlock();
}
resource.doLogging();
}

}

As you can see that, I am using tryLock() method to make sure my thread waits only for definite time and if it’s not getting the lock on object, it’s just logging and exiting. Another important point to note is the use of try-finally block to make sure lock is released even if doSomething() method call throws any exception.


Java Lock vs synchronized

Based on above details and program, we can easily conclude following differences between Java Lock and synchronization.

  1. Java Lock API provides more visibility and options for locking, unlike synchronized where a thread might end up waiting indefinitely for the lock, we can use tryLock() to make sure thread waits for specific time only.
  2. Synchronization code is much cleaner and easy to maintain whereas with Lock we are forced to have try-finally block to make sure Lock is released even if some exception is thrown between lock() and unlock() method calls.
  3. synchronization blocks or methods can cover only one method whereas we can acquire the lock in one method and release it in another method with Lock API.
  4. synchronized keyword doesn’t provide fairness whereas we can set fairness to true while creating ReentrantLock object so that longest waiting thread gets the lock first.
  5. We can create different conditions for Lock and different thread can await() for different conditions.

That’s all for Java Lock example, ReentrantLock in java and a comparative analysis with synchronized keyword.


About Pankaj

If you have come this far, it means that you liked what you are reading. Why not reach little more and connect with me directly on Google Plus, Facebook or Twitter. I would love to hear your thoughts and opinions on my articles directly.

Recently I started creating video tutorials too, so do check out my videos on Youtube.

Java Lock Example – ReentrantLock(java锁的例子)的更多相关文章

  1. Java - "JUC" ReentrantLock获取锁

    [Java并发编程实战]-----“J.U.C”:ReentrantLock之一简介 ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”. 顾名思义,R ...

  2. Java并发编程:同步锁、读写锁

    之前我们说过线程安全问题可以用锁机制来解决,即线程必要要先获得锁,之后才能进行其他操作.其实在 Java 的 API 中有这样一些锁类可以提供给我们使用,与其他对象作为锁相比,它们具有更强大的功能. ...

  3. Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example(ScheduledThreadPoolExecutor例子——了解如何创建一个周期任务)

    Welcome to the Java Scheduler Example. Today we will look into ScheduledExecutorService and it's imp ...

  4. Java线程新特征——Java并发库

    一.线程池   Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...

  5. 《深入浅出 Java Concurrency》—锁紧机构(一)Lock与ReentrantLock

    转会:http://www.blogjava.net/xylz/archive/2010/07/05/325274.html 前面的章节主要谈谈原子操作,至于与原子操作一些相关的问题或者说陷阱就放到最 ...

  6. 深入浅出 Java Concurrency (6): 锁机制 part 1 Lock与ReentrantLock

      前面的章节主要谈谈原子操作,至于与原子操作一些相关的问题或者说陷阱就放到最后的总结篇来整体说明.从这一章开始花少量的篇幅谈谈锁机制. 上一个章节中谈到了锁机制,并且针对于原子操作谈了一些相关的概念 ...

  7. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  8. 12、java5锁java.util.concurrent.locks.Lock之ReentrantLock

    JDK文档描述: public interface LockLock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作.此实现允许更灵活的结构,可以具有差别很大的属性,可 ...

  9. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

随机推荐

  1. ShopNC【B2B2C】多用户电商平台系统,带WAP,微商城,圈子,门户

    <ShopNC[B2B2C]多用户电商平台系统,带WAP,微商城,圈子,门户> 早上发了套ShopNC B2B2C多用户商城2014商业版,带微商城,但不带圈子.WAP.圈子和门户,如今发 ...

  2. jquery事件 【mousedown与mouseup ----keydown与keypress与keyup】focus--blur--orrer--pageX-pageY

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> ...

  3. HDU 5281 Senior&#39;s Gun 杀怪

    题意:给出n把枪和m个怪.每把枪有一个攻击力,每一个怪有一个防御力.假设某把枪的攻击力不小于某个怪的防御力则能将怪秒杀,否则无法杀死.一把枪最多仅仅能杀一个怪,不能用多把枪杀同一个怪.每杀一次怪能够得 ...

  4. Nginx+tomcat+ssl免费证书配置

    0.说明 本文说描写叙述的方式是用nginx的443重定向到tomcat的8443,nginx的80port重定到tomcat的8080: 乱入:个人标记:caicongyang 1.nginx安装 ...

  5. 如何实现对网站页面访问量的统计(javaweb和php)

    如何实现对网站页面访问量的统计(javaweb和php) 一.总结 一句话总结:其实很简单啦,每访问一次那个页面对应的index函数(控制器中的那个函数)访问次数就加1就可以了. 1.javaweb中 ...

  6. git 版本管理工具说明

    $ git init                 (初始化本地仓库,会生成.git 文件夹  .git 文件夹里存储了所有的版本信息.标记等内容) $ git add .              ...

  7. 全面了解Linux下Proc文件系统

    全面了解Linux下Proc文件系统   Proc是一个虚拟文件系统,在Linux系统中它被挂载于/proc目录之上.Proc有多个功能 ,这其中包括用户可以通过它访问内核信息或用于排错,这其中一个非 ...

  8. Atcoder ABC 071 C,D

    C - Make a Rectangle Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement W ...

  9. 通过 chroot 重新设置 root 密码

    实例:通过 chroot 重新设置 root 密码 忘记了 root 密码该怎么办?接下来的 demo 将演示如何通过 chroot 命令重新设置 centos7 中被忘记了的 root 密码.sys ...

  10. springboot整合Beetl、BeetlSql实现ajax分页

    Beetl是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,它功能强大,性能良好,超过当前流行的模板引擎.而且还易学易用. BeetSql是一个 ...