ReentrantLock简称可重入的互斥锁,当一个线程多次获取它所占有的锁资源时,是可以成功的,每当成功获取一次的时候,其保持计数将会+1,并且在其执行完毕释放锁的时候,保持计数随之清零;至于互斥的概念,就是当一个线程持有该锁时,其他需要获取该锁的线程将一直等待直至该锁被释放;这是多线程中实现同步的一种方式,它实现了synchronized的基本功能,同时也拓展了一些新的方法。
synchronized和ReentrantLock的区别:
除了synchronized的功能,多了三个高级功能:等待可中断,公平锁,绑定多个Condition.
1.等待可中断
在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待. tryLock(long timeout, TimeUnit unit)
2.公平锁
按照申请锁的顺序来一次获得锁称为公平锁.synchronized的是非公平锁,ReentrantLock可以通过构造函数实现公平锁. new RenentrantLock(boolean fair)
3.绑定多个Condition
通过多次newCondition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步的功能.通过await(),signal();
- 首先声明一个银行卡的辅助类
package com.test.demo; public class BankCard { private String cardNo; private int balance; public String getCardNo() { return cardNo; } public void setCardNo(String cardNo) { this.cardNo = cardNo; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } }
- 创建Husband类执行存钱操作
package com.test.demo; import java.util.concurrent.locks.Lock; public class Husband implements Runnable{ private BankCard card; private Lock lock; public Husband(BankCard card, Lock lock){ this.card = card; this.lock = lock; } public void run() { while(true){ lock.lock(); System.out.println("丈夫准备存钱,账户余额为: "+ card.getBalance()); card.setBalance(card.getBalance() + 500); System.out.println("丈夫存钱完毕,账户余额为: " + card.getBalance()); lock.unlock(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
- 创建Wife类执行消费操作
package com.test.demo; import java.util.concurrent.locks.Lock; public class Wife implements Runnable{ private BankCard card; private Lock lock; public Wife(BankCard card, Lock lock){ this.card = card; this.lock = lock; } public void run() { while(true){ lock.lock(); System.out.println("妻子要消费,账户余额为: "+ card.getBalance()); card.setBalance(card.getBalance() - 1000); System.out.println("妻子消费完毕,账户余额为:" +card.getBalance()); lock.unlock(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
- 启动线程进行测试
package com.test.demo; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Hello world! * */ public class App { public static void main( String[] args ) { BankCard card = new BankCard(); card.setBalance(10000); Lock lock = new ReentrantLock(); Wife child = new Wife(card, lock); Husband father = new Husband(card, lock); new Thread(child).start(); new Thread(father).start(); } }
运行效果如下,我们可以看到正常操作
丈夫准备存钱,账户余额为: 10000 丈夫存钱完毕,账户余额为: 10500 妻子要消费,账户余额为: 10500 妻子消费完毕,账户余额为:9500 妻子要消费,账户余额为: 9500 妻子消费完毕,账户余额为:8500 丈夫准备存钱,账户余额为: 8500 丈夫存钱完毕,账户余额为: 9000 妻子要消费,账户余额为: 9000 妻子消费完毕,账户余额为:8000 丈夫准备存钱,账户余额为: 8000 丈夫存钱完毕,账户余额为: 8500 丈夫准备存钱,账户余额为: 8500 丈夫存钱完毕,账户余额为: 9000 妻子要消费,账户余额为: 9000 妻子消费完毕,账户余额为:8000
- 当妻子锁定后不释放锁
package com.test.demo; import java.util.concurrent.locks.Lock; public class Wife implements Runnable{ private BankCard card; private Lock lock; public Wife(BankCard card, Lock lock){ this.card = card; this.lock = lock; } public void run() { while(true){ lock.lock(); System.out.println("妻子要消费,账户余额为: "+ card.getBalance()); card.setBalance(card.getBalance() - 1000); System.out.println("妻子消费完毕,账户余额为:" +card.getBalance()); //lock.unlock(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
运行效果如下:
妻子要消费,账户余额为: 10000 妻子消费完毕,账户余额为:9000 妻子要消费,账户余额为: 9000 妻子消费完毕,账户余额为:8000 妻子要消费,账户余额为: 8000 妻子消费完毕,账户余额为:7000 妻子要消费,账户余额为: 7000 妻子消费完毕,账户余额为:6000 妻子要消费,账户余额为: 6000 妻子消费完毕,账户余额为:5000 妻子要消费,账户余额为: 5000 妻子消费完毕,账户余额为:4000 妻子要消费,账户余额为: 4000 妻子消费完毕,账户余额为:3000 妻子要消费,账户余额为: 3000 妻子消费完毕,账户余额为:2000 妻子要消费,账户余额为: 2000 妻子消费完毕,账户余额为:1000
可以看到获取不到锁的Husband线程将一直处于阻塞状态!
除此之外,ReentrantLock提供了灵活的中断机制,第一种:ReentrantLock尝试获取锁时,可以指定等待的时间,当超过等待时间后则放弃执行并返回一个boolean值;第二种:ReentrantLock提供了可中断锁操作。
try { if (lock.tryLock(5, TimeUnit.SECONDS)) { //如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行 try { //操作 } finally { lock.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException }
以上为本次的简单演示,仅仅供个人的学习所用!
相关推荐
java语言 并发编程 ReentrantLock与synchronized区别 详解
总结来说,`synchronized`适用于简单的同步需求,而`ReentrantLock`在需要更细粒度控制、中断锁、公平性等高级特性的场合更为适用。在实际编程中,根据具体需求选择合适的方式,能有效提升并发程序的稳定性和性能。...
### ReentrantLock 与 synchronized 的比较 #### 一、引言 在Java中,多线程和并发控制一直是程序员关注的重点。随着Java的发展,其语言本身及标准库提供了丰富的工具来帮助开发者处理并发问题。其中,`...
然而,两者之间存在一些显著的区别,这些差异体现在功能、灵活性、性能以及使用场景上。 首先,synchronized是Java内置的同步机制,它提供了互斥和可见性保证。在Java 5之前,它是唯一的同步手段。synchronized可以...
在Java并发编程中,理解和熟练...总的来说,Java并发编程中的锁机制是确保线程安全的关键,理解并熟练使用`synchronized`和`ReentrantLock`,以及相应的等待/通知机制,能够帮助开发者设计出高效且可靠的多线程程序。
本文将深入探讨Synchronized关键字锁和ReentrantLock锁的异同、功能特性以及它们在实际应用中的适用场景。 首先,Synchronized是一种内置的Java关键字,它提供了简单而强大的线程同步机制。当一个线程进入一个由...
第15讲丨synchronized和ReentrantLock有什么区别呢?.html
本文将深入探讨四种关键的并发控制机制:synchronized关键字、ReentrantLock(可重入锁)、volatile关键字以及Atomic类的原理与应用。 ### 1. synchronized关键字 `synchronized`关键字是Java提供的内置锁,用于...
下面我们将详细讨论它们的区别、性能、特性以及使用上的差异。 1. **功能对比**: - `synchronized`是一种内置锁,其使用简单,代码简洁。它具有线程同步的基本功能,包括可重入性和内存可见性。在大多数情况下,...
Lock、Synchronized 和 ReentrantLock 的使用 Lock、Synchronized 和 ReentrantLock 是 Java 中三种常用的同步机制,每种机制都有其特点和使用场景。下面对这三种机制进行详细的分析和比较。 一、Synchronized ...
`ReentrantLock`是Java并发编程中的一种高级锁机制,它是`java.util.concurrent.locks`包中的类,提供了比`synchronized`关键字更丰富的功能和更细粒度的控制。相较于`synchronized`,`ReentrantLock`的主要优势在于...
Java并发之ReentrantLock类源码解析 ReentrantLock是Java并发包中的一种同步工具,它可以实现可重入锁的功能。ReentrantLock类的源码分析对理解Java并发机制非常重要。本文将对ReentrantLock类的源码进行详细分析,...
在ReentrantLock中,Unsafe用于初始化AQS实例,设置和获取`state`字段,以及实现锁的原子操作,如compareAndSwapInt()方法用于无锁操作,保证了并发安全性。 此外,ReentrantLock还支持公平锁和非公平锁两种模式。...
本文将详细探讨`synchronized`的关键特性、用法以及它在实际开发中的应用。 1. **synchronized的两种使用方式** - **方法同步**:在方法声明前加上`synchronized`关键字,这将使得整个方法成为同步方法,每次只有...
本文将深入探讨ReentrantLock的原理,特别是其公平锁与非公平锁的概念,以及ReentrantLock的源码解析。 首先,我们了解什么是可重入锁。可重入锁允许一个线程多次获取同一锁,而不被阻塞。当一个线程已经持有了锁,...
在Java 5之后,引入了`java.util.concurrent`包,其中的`ReentrantLock`类提供了可重入锁,它具有与`synchronized`相似的功能,但更加灵活,支持公平锁、非公平锁以及可中断的锁等待。 **5. synchronized的应用示例...
背景,应该就是Synchronized的缺点Synchronized产生原因,原子性(Atomicity)与可见性(visibility),其中可见性涉及到JM
1. **ReentrantLock**:具有`synchronized`的可重入性,并且提供公平锁、非公平锁选择,支持尝试获取锁、中断锁等待等高级功能。 2. **Semaphore**:信号量,可以控制同时访问特定资源的线程数量。 3. **...
本文将深入解析`synchronized`的工作原理、使用方式以及它在并发编程中的重要性。通过分析提供的源码,我们可以更直观地理解这个关键字的实际应用。 `synchronized`关键字主要有两种用法:修饰实例方法和同步代码块...