Java并发——synchronized和ReentrantLock的联系与区别
0 前言
本文通过使用synchronized以及Lock分别完成“生产消费场景”,再引出两种锁机制的关系和区别,以及一些关于锁的知识点。
本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52401134
1. synchronized, wait, notify结合实现生产消费场景
1.1 生产者类
/*
*@author SEU_Calvin
*@date 2016/09/01
*/
public class Producer implements Runnable {
@Override
public void run() {
int count = LockTest.count;
while (count <= 3) {
synchronized (LockTest.obj) {
LockTest.count++;
System.out.println("生产者生产产品...现在有"+LockTest.count+"个");
if(LockTest.count >= 3){
System.out.println("现在产品充足,待消费...");
LockTest.obj.notify();// 主动释放对象锁
try {
LockTest.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}
}
}
1.2 消费者类
/*
*@author SEU_Calvin
*@date 2016/09/01
*/
public class Consumer implements Runnable {
@Override
public synchronized void run() {
int count = LockTest.count;
while (count >= 0) {
synchronized (LockTest.obj) {
LockTest.count--;
System.out.println("消费者消费产品...现在有"+LockTest.count+"个");
if(LockTest.count <= 0){
System.out.println("现在产品缺货,待生产...");
LockTest.obj.notify(); // 主动释放对象锁
try {
LockTest.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}
}
}
1.3 测试类
public class LockTest {
public static final Object obj = new Object();
public static int count = 0;
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
}
1.4 运行结果
这个实例比较简单,主要是通过synchronized,wait, notify结合来实现线程的顺序切换。
2. Lock类
除了wait()、notify()以及synchronized协作完成线程同步之外,使用Lock也可以达到同样的目的。
/*
*@author SEU_Calvin
*@date 2016/09/01
*/
public class ReentrantLockTest {
private volatile int stopFalg = 10;//控制程序执行次数
private volatile int count = 0;
private Lock lock = new ReentrantLock();
private ArrayList<Thread> threads = new ArrayList<Thread>(); public static void main(String[] args) throws InterruptedException {
final ReentrantLockTest test = new ReentrantLockTest();
new Thread("Producer") { //开启生产者线程
public void run() {
test.threads.add(this);
while (test.stopFalg > 0) {
test.operateResource(this.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
Thread.sleep(1000); //保证生产者线程先启动,继而两者同时生产、消费
new Thread("Consumer") { //开启消费者线程
public void run() {
test.threads.add(this);
while (test.stopFalg > 0) {
test.operateResource(this.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
} public void operateResource(String id) {
lock.lock(); //lock开启,锁两个线程都会访问到的同一区域的代码
try {
if ("Producer".equals(id)) { //判断线程类型
if (count < 10) {
count++;
stopFalg--;
System.out.println("Producer=>" + count);
}
} else if ("Consumer".equals(id)) {//判断线程类型
if (count > 0) {
count--;
System.out.println("Consumer=>" + count);
}
}
} finally {
lock.unlock();//必须unlock
}
}
}
2.1 运行结果
3. 两者关系与区别汇总
从上面两个实例的实现可以引出Synchronized和Lock的关系:
(1)ReentrantLock与synchronized有相同的并发性和内存语义。但是ReentrantLock还包含了区别于synchronized的以下特性。
(2)等待可中断:在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待。有效防止了死锁。
lock();//用来获取锁,如果锁已被其他线程获取,则进行等待
tryLock(); //尝试获取锁,若成功返回true,失败(即锁已被其他线程获取)则返回false
tryLock(long timeout, TimeUnit unit); //在拿不到锁时会等待一定的时间
//两个线程同时通过lock.lockInterruptibly()想获取某个锁时
//若线程A获取到了锁,而线程B在等待
//线程B调用threadB.interrupt()方法能够中断线程B的等待过程
lockInterruptibly();
(3)公平锁:按照申请锁的顺序来获得锁。synchronized是非公平锁。ReentrantLock可以通过构造函数实现公平锁。
new RenentrantLock(boolean fair);
(4)绑定多个Condition,添加多个检控条件:通过多次new Condition可以获得多个Condition对象。
(5)ReentrantLock可以获取各种锁的信息,比如可以查看锁的状态,锁是否被锁上了。可以查看当前有多少线程在等待锁。
(6)Lock使用更灵活、性能更佳。性能的优化体现在,当许多线程都想访问共享资源时,JVM可以花更少的时间来调度线程,把更多时间用在执行线程上。
(7)由于synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否,而ReentrantLock使用代码实现的,系统无法自动释放锁,需要在代码中finally子句中显式释放锁lock.unlock()。同时由于ReentrantLock是类,使用时需要import相关类。
(8)总结:在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态。
4. 可重入锁
synchronized以及Lock类锁,两者都是可重入锁。
class MyClass {
public synchronized void method1() {
method2();
}
public synchronized void method2() {
}
}
可重入锁的意思是,当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。假如synchronized不具备可重入性,此时线程A需要重新申请锁。但是线程A已经持有了该对象的锁,这样线程A会一直等待永远不会获取到的锁。
Java并发——synchronized和ReentrantLock的联系与区别的更多相关文章
- java并发编程——通过ReentrantLock,Condition实现银行存取款
java.util.concurrent.locks包为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器.该框架允许更灵活地使用锁和条件,但以更难用的语法为代价. Lock 接口 ...
- java 并发——synchronized
java 并发--synchronized 介绍 在平常我们开发的过程中可能会遇到线程安全性的问题,为了保证线程之间操作数据的正确性,我们第一想到的可能就是使用 synchronized 并且 syn ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- Java并发——synchronized关键字
前言: 只要涉及到Java并发那么我们就会考虑线程安全,实际上能够实现线程安全的方法很多,今天先介绍一下synchronized关键字,主要从使用,原理介绍 一.synchronized的使用方法 1 ...
- Java并发-Synchronized关键字
一.多线程下的i++操作的并发问题 package passtra; public class SynchronizedDemo implements Runnable{ private static ...
- Java锁Synchronized对象锁和类锁区别
java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...
- Java并发编程基础-ReentrantLock的机制
同步锁: 我们知道,锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源,在Lock接口出现之前,Java应用程序只能依靠synchronized关键字来实现同步锁 ...
- [Java] [Lock] [Synchronized VS ReentrantLock]
Overview java编写多线程程序时,为了保证线程安全,需要对数据进行同步,经常用到的两种同步方式就是synchronized和重入锁ReentrantLock. 相似点 都是加锁方式 都是阻塞 ...
- java并发编程基础-ReentrantLock及LinkedBlockingQueue源码分析
ReentrantLock是一个较为常用的锁对象.在上次分析的uil开源项目中也多次被用到,下面谈谈其概念和基本使用. 概念 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 相 ...
随机推荐
- 华为云kafka POC 踩坑记录
2019/03/08 18:29 最近在进行华为云相关POC验证,个人主要负责华为云DMS kafka相关.大致数据流程是,从DIS取出数据,进行解析处理,然后放入kafka,再从kafka中取出数据 ...
- java 多线程之取消与关闭
要使线程安全,快速,可靠的停下来并不是一件容易的事情.java并没有提供任何机制来安全的终止线程.但是java提供了中断(interrupt)使一个线程可以终止另一个线程的当前工作 每个线程都有一个b ...
- parameter与attribute的使用场合(转载自草原和大树)
Attribute 和 Parameter 的区别 (1)HttpServletRequest类有setAttribute()方法,而没有setParameter()方法 (2)当两个Web组件之间为 ...
- 为什么要使用Vuex?
为什么要使用Vuex? 1. 假如不使用 1.1 父子组件依赖同一个state 1.2 兄弟组件依赖同一个state 2. 用了Vuex之后 3. 方便记忆和理解
- 正则表达式---01 js篇
本文主要针对js中正则表达式的实践操作,来让大家对正则表达式有一个入门清晰的了解. 正则表达式推荐学习网址:http://www.runoob.com/regexp/regexp-tutorial.h ...
- 利用BandwagonHost***便宜Linux VPS安装VNC(远程桌面)- 安装篇
如果我们有搭建过网站,或者用过VPS.服务器,肯定会看到最近几年主机市场竞争还是比较激烈的.尤其是VPS.服务器的价格走低,很多商家价格厮杀的厉害,甚至出现年付几美元的VPS.便宜VPS固然是好事,我 ...
- codevs 2620 战壕
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description Smart和Sarah正在玩一个即时战略游戏. Smart在他的基地附近建立了n个 ...
- 系统装更新补丁出现“正在此计算机上搜索更新”,有时等待N长时间也没有反应
系统装更新补丁出现“正在此计算机上搜索更新”,有时等待N长时间也没有反应 管理员身份运行 net stop wuauserv net stop CryptSvc ren %windir%\system ...
- SQL 使用触发器常见错误
今天做代码审查时,看见以下一段触发器的创建脚本,我们一起来分析一下 create trigger [trigger_puClassRoomType] on [dbo].[puClassRoomType ...
- Python http
# import httplib # http_client = None # http_client = httplib.HTTPConnection('localhost', 8080, time ...