1、效果和synchronized一样,都可以同步执行,lock方法获得锁,unlock方法释放锁

使用示例:

package com.test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MyService { private Lock lock = new ReentrantLock();
public void methodA() {
try {
lock.lock();
System.out.println("methodA begin ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("methodA end ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void methodB() {
try {
lock.lock();
System.out.println("methodB begin ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("methodB end ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package com.test;

public class Run {

    public static void main(String[] args) {

        MyService myService = new MyService();
Thread t1 = new Thread(new Runnable() { @Override
public void run() {
myService.methodA();
}
});
Thread t2 = new Thread(new Runnable() { @Override
public void run() {
myService.methodB();
}
});
t1.start();
t2.start();
}
}
结果:
methodA begin ThreadName = Thread-0time=
methodA end ThreadName = Thread-0time=
methodB begin ThreadName = Thread-1time=
methodB end ThreadName = Thread-1time=

注意:必须要在finally块里调用lock.unlock() 释放锁.

2、使用Condition实现等待/通知:

  awati() 与 signal() 方法:

  

package com.test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MyService { private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition(); public void testWait() {
try {
lock.lock();
System.out.println("wait");
condition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void testSignal() {
try {
lock.lock();
condition.signal();
} finally {
lock.unlock();
}
} }
  • 通过Condition对象来使线程wait,必须先执行lock.lock()获得锁。
  • Condition对象的signal()方法可以唤醒线程.
  • Condition的awati()方法和Object 中的wati()方法等效.
  • Condition的signal()方法和Object 中的notify()方法等效.
  • Condition的signalAll()方法和Object中的notifyAll()方法等效。

3、公平锁和非公平锁:

  公平锁标识线程获取锁的顺序是按照线程加锁的顺序来分配的。即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得锁的。

  

Lock lock=new ReentrantLock(true);//公平锁
Lock lock=new ReentrantLock(false);//非公平锁

4、ReentrantLock 类的方法:

  • int getHoldCount() 的作用是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
  • int getQueueLength()的所用是返回正在等待获取此锁的线程估计数 。比如有5个线程,1个线程首先执行await()方法,那么调用此方法的返回值是4.
  • int getWaitQueueLength(Condition condition)的所用是返回等待与此锁定相关的给定条件Condition的线程估计数,比如5个线程都执行了Condition的await()方法 ,那么返回值就是5.
  • boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁.
  • boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的condition条件。
  • boolean isFair()的作用是判断是不是公平锁.
  • boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁。
  • boolean isLocked()的作用是查询此锁是否由任意线程保持。
  • void lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
  • boolean tryLock()的作用是仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。
  • boolean tryLock(long timeout, TimeUnit unit) 的作用是,如果锁定在给定等待时间内没有被领一个线程保持,且当前线程未被中断,则获取该锁定。

5、ReentrantReadWriteLock 类,读写锁:

  类ReentrantLock 具有完全互斥排他的效果,即同一时间只有一个线程在执行lock()方法后面的任务。

  读写锁表示也有两个锁,一个是读操作相关的锁,也成为共享锁;另一个是写操作相关的锁,也就排它锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。在没有线程进行写操作时,进行读取操作的多个线程都可以获取读锁,而进行写入操作的线程只有在获取写锁后才能进行写入操作。即多个线程可以同时进行读操作,但同一时刻只有一个线程可以进行写操作。

  • 读读共享

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("获取读锁:" + System.currentTimeMillis());
Thread.sleep(1000);
} finally {
lock.readLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
  • 写写互斥

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("获取写锁:" + System.currentTimeMillis());
Thread.sleep(1000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
  • 读写互斥

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
try {
try {
lock.writeLock().lock();
System.out.println("获取读锁:" + System.currentTimeMillis());
Thread.sleep(1000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
} public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("获取写锁:" + System.currentTimeMillis());
Thread.sleep(1000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}

 lock 与 lockInterruptibly比较区别在于:
 lock 优先考虑获取锁,待获取锁成功后,才响应中断。
 lockInterruptibly 优先考虑响应中断,而不是响应锁的普通获取或重入获取

synchronized 和 lock 的用法区别:

  1. synchronized 是托管给JVM执行的。而Lock是Java写的控制锁的代码。
  2. synchronized 原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,会导致效率很低。
  3. Lock用的是乐观锁方式。每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试。直到成功为止。
  4. ReentrantLock必须在finally中释放锁,而synchronized不需要。
  5. ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁。而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。
  6. synchronized的话,锁的范围是整个方法或synchronized块部分;而Lock因为是方法调用,可以跨方法,灵活性更大。

使用ReentrantLock的场景:

  1. 某个线程在等待一个锁的控制权的这段时间需要中断。
  2. 需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程.
  3. 具有公平锁功能,每个到来的线程都将排队等候.

java ReentranLock锁的更多相关文章

  1. Java的锁

    今天练习了Java的多线程,提到多线程就基本就会用到锁 Java通过关键字及几个类实现了锁的机制,这里先介绍下Java都有哪些锁:   一.Java实现锁的机制: Java运行到包含锁的代码时,获取尝 ...

  2. java的锁机制

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...

  3. JAVA线程锁-读写锁

    JAVA线程锁,除Lock的传统锁,又有两种特殊锁,叫读写锁ReadWriteLock 其中多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 例子: /** * java线程锁分为读写锁 ReadWri ...

  4. Java线程锁一个简单Lock

    /** * @author * * Lock 是java.util.concurrent.locks下提供的java线程锁,作用跟synchronized类似, * 单是比它更加面向对象,两个线程执行 ...

  5. paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象)

    paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象) 1     锁的缺点 2     CAS(Compare ...

  6. Java偏向锁实现原理(Biased Locking)

    http://kenwublog.com/theory-of-java-biased-locking 阅读本文的读者,需要对Java轻量级锁有一定的了解,知道lock record, mark wor ...

  7. Java分布式锁之数据库实现

    之前的文章<Java分布式锁实现>中列举了分布式锁的3种实现方式,分别是基于数据库实现,基于缓存实现和基于zookeeper实现.三种实现方式各有可取之处,本篇文章就详细讲解一下Java分 ...

  8. Java类锁和对象锁

    一.类锁和对象锁 二.使用注意 三.参考资料 一.类锁和对象锁 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class) 对象锁:在代码 ...

  9. java的锁机制——synchronized

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...

随机推荐

  1. SqL注入攻击实践

    研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理 缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量.溢出的数据覆盖在合法数据上.理想情况是,程序检查数据长 ...

  2. MyEclipse异常关闭导致启动不了tomcat的解决方法

     由于MyEclipse的异常关闭从而导致Tomcat并没有关闭,所以再次启动Tomcat当然是无法启动的啦,解决方法:在任务管理器中关闭一个叫javaw.exe的进程,如果你这时已经启动了MyEcl ...

  3. <十八>UML核心视图动态视图之协作图

    一:协作图 --->描述了对象间交互的一种模式.它通过对象之间的连接和它们相互发送的消息来显示参与交互的对象 --->协作图可以有对象和主角实例,以及描述它们之间关系和交互的连接和消息.通 ...

  4. 瞎写的树dfs序

    这里枚举了树的DFS序来解决树上问题的多个板子,自己最好多看看. ↓改↓ ↓求↓ 点 点 ————————>>>这个就算了 点 树 简单, BIT 点 链 重点! 树 树 简单, 线 ...

  5. 1067 Bash 游戏v2

    传送门 1067 Bash游戏 V2 基准时间限制:1 秒 空间限制:131072 KB 分值: 10   有一堆石子共有N个.A B两个人轮流拿,A先拿.每次只能拿1,3,4颗,拿到最后1颗石子的人 ...

  6. Java中的数组和方法

    3.1 数组的定义和使用 数组(Array)是用来存储一组相同数据类型数据的集合.数组中的每个数据称为一个元素(element),数组可以分为一维数组,二维数组和多维数组.我们 主要讲解一维数组和二维 ...

  7. 【242】◀▶IEW-Unit07

    Unit 7 Education: Schools I.句子基本结构在写作中的运用 主谓宾 主系表 主谓 主谓宾宾 主谓宾补 1.主语: 1)位于句首 2)名词 例句:应该建立相关法律 Laws an ...

  8. 【238】◀▶IEW-Unit03

    Unit 3 Media 柱状图 1.图片及model1分析 The graph below contains information about the average science test s ...

  9. [hdu4405]Aeroplane chess(概率dp)

    题意:某人掷骰子,数轴上前进相应的步数,会有瞬移的情况,求从0到N所需要的期望投掷次数. 解题关键:期望dp的套路解法,一个状态可以转化为6个状态,则该状态的期望,可以由6个状态转化而来.再加上两个状 ...

  10. MAF框架的使用限制

    虽然MAF实现了插件式开发,动态热插拨,AppDomain隔离等诸多优点,但是正因为它复杂的功能机制也带来了很多其它方面的使用限制,下面列出官方给出的MAF框架的使用限制. 1) 在应用主程序显示的插 ...