`
newbee_zc
  • 浏览: 30856 次
文章分类
社区版块
存档分类
最新评论

ReentrantLock synchronized的区别以及简单示范

阅读更多

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                 
                }

 

 

 

 

以上为本次的简单演示,仅仅供个人的学习所用!

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    ReentrantLock与synchronized区别

    java语言 并发编程 ReentrantLock与synchronized区别 详解

    ReentrantLock与synchronized

    总结来说,`synchronized`适用于简单的同步需求,而`ReentrantLock`在需要更细粒度控制、中断锁、公平性等高级特性的场合更为适用。在实际编程中,根据具体需求选择合适的方式,能有效提升并发程序的稳定性和性能。...

    ReentrantLock 与 synchronized 简介

    ### ReentrantLock 与 synchronized 的比较 #### 一、引言 在Java中,多线程和并发控制一直是程序员关注的重点。随着Java的发展,其语言本身及标准库提供了丰富的工具来帮助开发者处理并发问题。其中,`...

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    然而,两者之间存在一些显著的区别,这些差异体现在功能、灵活性、性能以及使用场景上。 首先,synchronized是Java内置的同步机制,它提供了互斥和可见性保证。在Java 5之前,它是唯一的同步手段。synchronized可以...

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    在Java并发编程中,理解和熟练...总的来说,Java并发编程中的锁机制是确保线程安全的关键,理解并熟练使用`synchronized`和`ReentrantLock`,以及相应的等待/通知机制,能够帮助开发者设计出高效且可靠的多线程程序。

    简单聊聊Synchronized和ReentrantLock锁.docx

    本文将深入探讨Synchronized关键字锁和ReentrantLock锁的异同、功能特性以及它们在实际应用中的适用场景。 首先,Synchronized是一种内置的Java关键字,它提供了简单而强大的线程同步机制。当一个线程进入一个由...

    第15讲丨synchronized和ReentrantLock有什么区别呢?.html

    第15讲丨synchronized和ReentrantLock有什么区别呢?.html

    synchronized ReentrantLock volatile Atomic 原理分析.docx

    本文将深入探讨四种关键的并发控制机制:synchronized关键字、ReentrantLock(可重入锁)、volatile关键字以及Atomic类的原理与应用。 ### 1. synchronized关键字 `synchronized`关键字是Java提供的内置锁,用于...

    22 到底哪把锁更适合你?—synchronized与ReentrantLock对比.pdf

    下面我们将详细讨论它们的区别、性能、特性以及使用上的差异。 1. **功能对比**: - `synchronized`是一种内置锁,其使用简单,代码简洁。它具有线程同步的基本功能,包括可重入性和内存可见性。在大多数情况下,...

    Lock、Synchoronized和ReentrantLock的使用

    Lock、Synchronized 和 ReentrantLock 的使用 Lock、Synchronized 和 ReentrantLock 是 Java 中三种常用的同步机制,每种机制都有其特点和使用场景。下面对这三种机制进行详细的分析和比较。 一、Synchronized ...

    java ReentrantLock详解.docx

    `ReentrantLock`是Java并发编程中的一种高级锁机制,它是`java.util.concurrent.locks`包中的类,提供了比`synchronized`关键字更丰富的功能和更细粒度的控制。相较于`synchronized`,`ReentrantLock`的主要优势在于...

    Java中ReentrantLock的使用.docx

    Java中的ReentrantLock是线程安全编程中的一种高级锁机制,它属于Lock接口的一个实现,提供了比synchronized更丰富的功能和更高的灵活性。ReentrantLock的名字来源于它的可重入性,这意味着一个线程可以多次获取同一...

    Java并发之ReentrantLock类源码解析

    Java并发之ReentrantLock类源码解析 ReentrantLock是Java并发包中的一种同步工具,它可以实现可重入锁的功能。ReentrantLock类的源码分析对理解Java并发机制非常重要。本文将对ReentrantLock类的源码进行详细分析,...

    ReentrantLock解析

    在ReentrantLock中,Unsafe用于初始化AQS实例,设置和获取`state`字段,以及实现锁的原子操作,如compareAndSwapInt()方法用于无锁操作,保证了并发安全性。 此外,ReentrantLock还支持公平锁和非公平锁两种模式。...

    synchronized关键字的实质及用法

    本文将详细探讨`synchronized`的关键特性、用法以及它在实际开发中的应用。 1. **synchronized的两种使用方式** - **方法同步**:在方法声明前加上`synchronized`关键字,这将使得整个方法成为同步方法,每次只有...

    ReentrantLock源码的使用问题详解.docx

    本文将深入探讨ReentrantLock的原理,特别是其公平锁与非公平锁的概念,以及ReentrantLock的源码解析。 首先,我们了解什么是可重入锁。可重入锁允许一个线程多次获取同一锁,而不被阻塞。当一个线程已经持有了锁,...

    java同步synchronized关键字用法示例

    在Java 5之后,引入了`java.util.concurrent`包,其中的`ReentrantLock`类提供了可重入锁,它具有与`synchronized`相似的功能,但更加灵活,支持公平锁、非公平锁以及可中断的锁等待。 **5. synchronized的应用示例...

    wangwang4git#just-do#简单说说Synchronized,ReentrantLock1

    背景,应该就是Synchronized的缺点Synchronized产生原因,原子性(Atomicity)与可见性(visibility),其中可见性涉及到JM

    Java synchronized使用案例

    1. **ReentrantLock**:具有`synchronized`的可重入性,并且提供公平锁、非公平锁选择,支持尝试获取锁、中断锁等待等高级功能。 2. **Semaphore**:信号量,可以控制同时访问特定资源的线程数量。 3. **...

Global site tag (gtag.js) - Google Analytics