`

Java多线程高并发篇(一)--重入锁

阅读更多

重入锁

为什么叫重入锁?是因为同一个线程可以重复进入自己获取的锁.

1.重入锁的特性

1.1重入锁比synchronized更灵活,它能够显式指定何时加锁,何时解锁.(实例方法lock(),unlock())

1.2中断响应

使用ReentrantLock的实例方法lockInterruptibly()方法(建议使用可以响应中断的锁),可以在线程要求中断的时候进行响应,避免死锁情况下一直等待.

 

public class ReentrantLockInterruptDemo implements Runnable {
	public static ReentrantLock lock1 = new ReentrantLock();
	public static ReentrantLock lock2 = new ReentrantLock();
	int i;
	public ReentrantLockInterruptDemo(int i){
		this.i = i;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			if(i==1){
				//对锁的请求,统一使用lockInterruptibly方法,这是一个可以对中断进行响应的锁申请动作.在等待锁的时候可以响应中断
				lock1.lockInterruptibly();
				try {
					Thread.sleep(500);
				} catch (Exception e) {
					// TODO: handle exception
				}
				lock2.lockInterruptibly();
			}else{
				//对锁的请求,统一使用lockInterruptibly方法,这是一个可以对中断进行响应的锁申请动作.在等待锁的时候可以响应中断
				lock2.lockInterruptibly();
				try {
					Thread.sleep(500);
				} catch (Exception e) {
					// TODO: handle exception
				}
				lock1.lockInterruptibly();
			}
		} catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally{
			if(lock1.isHeldByCurrentThread()){
				lock1.unlock();
			}else if(lock2.isHeldByCurrentThread()){
				lock2.unlock();
			}
			System.out.println(Thread.currentThread().getId()+":线程退出");
		}
	}

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Thread t1 = new Thread(new ReentrantLockInterruptDemo(1));
		Thread t2 = new Thread(new ReentrantLockInterruptDemo(2));
		t1.start();
		t2.start();
		Thread.sleep(2000);
		t2.interrupt();
	}

}

 

1.3锁申请等待限时

申请锁的时候(使用tryLock(timeout, unit)方法),可以指定等待时间,如果在指定时间内没有获取到锁,返回false,否则返回true;而无参的tryLock()方法,当前线程会去尝试获得锁,如果锁被其他线程占用,则立即返回false,不会引起线程等待.

 

public class ReentrantLockTryLockDemo implements Runnable {
	public static ReentrantLock lock = new ReentrantLock();
	
	@Override
	public void run() {
		try {
			System.out.println("我进来了,我要获取锁,我是_"+Thread.currentThread().getName());
			if(lock.tryLock(5, TimeUnit.SECONDS)){
				System.out.println("谁进来了?我是_"+Thread.currentThread().getName());
				Thread.sleep(6000);
			}else{
				System.out.println("没获取到锁,我走了_"+Thread.currentThread().getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(lock.isHeldByCurrentThread()){
				lock.unlock();
			}
		}
	}

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		ReentrantLockTryLockDemo rt = new ReentrantLockTryLockDemo();
		Thread t1 = new Thread(rt);
		Thread t2 = new Thread(rt);
		t1.start();
		t2.start();
	}

}

 

1.4公平锁设置

重入锁可以对锁的公平性进行设置.在ReentrantLock的构造函数中.公平锁需要维护一个队列(按照线程的进入顺序,不论优先级高低).

但是由于实现成本较高,性能比较低,因此默认情况下是非公平的.

public class ReentrantLockFairDemo implements Runnable {
	//设置公平锁
	public static ReentrantLock fairLock = new ReentrantLock(true);
	
	@Override
	public void run() {
		while(true){
			try {
				fairLock.lock();
				System.out.println("我是_"+Thread.currentThread().getName());
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				fairLock.unlock();
			}
		}
	}

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		ReentrantLockFairDemo rt = new ReentrantLockFairDemo();
		Thread t1 = new Thread(rt,"Thread_t1");
		Thread t2 = new Thread(rt,"Thread_t2");
		t1.start();
		t2.start();
	}

 

 

1.5重入锁的好伙伴:Condition条件对象

在synchronized中,我们可以使用Object对象提供的wait()和notify()方法实现线程的挂起和唤醒(线程Thread中的suspend和resume已经废弃).

换句话说,Object对象中的wait()和notify()方法是和synchronized合用起来完成线程的挂起和唤醒操作的.

在重入锁中,我们使用Condition条件对象与重入锁合用,来实现线程的挂起(await)与唤醒(singal).

在使用时,我们需要使用ReentrantLock中的实例方法newCondition()得到Condition对象,将重入锁与对应的Condition对象进行绑定,实现线程的等待与唤醒.

具体方法介绍如下:

await()方法:与Object类中的wait()方法类似,在Condition接口中,提供了方法await(),调用后使当前线程等待,同时释放当前锁.在等待过程中可以响应中断.

awaitUninterruptibly()方法:功能与await()一样,不同的是,在等待过程中不响应中断.

singal()方法:用于唤醒一个在等待队列中的线程.

singalAll()方法:用于唤醒所有在等待队列中的线程.

 

public class ReentrantLockCondition implements Runnable{
	public static ReentrantLock lock = new ReentrantLock();
	public static Condition condition = lock.newCondition();
	
	@Override
	public void run() {
		try {
			//加锁
			lock.lock();
			System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"获取锁执行等待....");
			//等待,并释放锁
			condition.await();
			System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"开始执行任务....");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"执行完成....");
			lock.unlock();
			System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"线程释放锁....");
		}
	}
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Thread t1 = new Thread(new ReentrantLockCondition());
		Thread t2 = new Thread(new ReentrantLockCondition());
		t1.start();
		t2.start();
		Thread.sleep(2000);
		System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"线程获取锁....");
		//重新获取锁
		lock.lock();
		//唤醒
		System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"线程通知T1....");
		condition.signalAll();
		//释放锁
		lock.unlock();
		System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"释放锁....");
	}
}

 

 

分享到:
评论

相关推荐

    Java 多线程与并发(12-26)-JUC锁- ReentrantReadWriteLock详解.pdf

    在Java多线程并发编程中,ReentrantReadWriteLock(可重入读写锁)是一个重要的同步工具,它属于Java并发包(java.util.concurrent.locks)中的一个类。这个锁提供了比标准的synchronized关键字更细粒度的控制,允许...

    Java 多线程与并发(11-26)-JUC锁- ReentrantLock详解.pdf

    Java中的ReentrantLock是Java并发包(java.util.concurrent.locks)中的一个高级锁,它是可重入的,意味着一个线程可以多次获取同一锁。在深入ReentrantLock之前,我们首先需要了解Java并发编程的基础,特别是Java...

    Java 多线程与并发(10-26)-JUC锁- 锁核心类AQS详解.pdf

    它是实现Java并发包中锁和其他同步器的基础框架,例如ReentrantLock(可重入锁)、Semaphore(信号量)、CountDownLatch(倒计时门闩)、CyclicBarrier(循环栅栏)以及ReentrantReadWriteLock(可重入读写锁)等。...

    Java 多线程与并发(9-26)-JUC锁- LockSupport详解.pdf

    LockSupport是Java中用于多线程同步的一个工具类,它提供了一组基础的线程阻塞和解除阻塞的方法。这个类位于java.util.concurrent.locks包下,是实现并发编程中AQS(AbstractQueuedSynchronizer)框架的重要基础之一...

    Java多线程与并发库高级应用

    并发库高级应用\多线程\Java

    Java多线程编程实战指南-核心篇

    《Java多线程编程实战指南-...通过《Java多线程编程实战指南-核心篇》,你可以深入了解Java并发编程的各个方面,提升在高并发场景下的编程能力。书中的案例和练习将帮助你更好地掌握理论知识,并将其应用于实际项目中。

    java 多线程高并发相关资料收集

    本文将围绕“Java多线程高并发相关资料收集”这一主题,详细探讨这两个领域的核心知识点。 首先,多线程是指在单个程序中同时执行多个线程。Java提供了一个强大的多线程支持,允许开发者创建、管理和控制多个执行...

    Java 多线程与并发(2-26)Java 并发 - 线程基础.pdf

    Java多线程与并发是Java编程中至关重要的一个领域,特别是在构建高性能、高并发的应用时。线程基础是理解并发编程的关键,它涉及到线程的状态转换、创建与使用方式、同步与协作机制等方面。 线程有五种基本状态: 1...

    Java 模拟线程并发

    Java 模拟线程并发是编程领域中的一个重要概念,尤其在多核处理器和高并发应用中,理解并熟练掌握线程并发技术对于提升程序性能至关重要。在Java中,线程并发可以通过多种方式实现,包括继承Thread类、实现Runnable...

    Java多线程实战精讲-带你一次搞明白Java多线程高并发

    Java多线程实战精讲是Java开发者必备的技能之一,特别是在处理高并发场景时,它的重要性不言而喻。本文将深入探讨Java多线程的相关知识点,帮助你全面理解并掌握这一核心概念。 1. **线程基础** - **线程定义**:...

    Java 多线程与并发(15-26)-JUC集合- ConcurrentLinkedQueue详解.pdf

    ### Java多线程与并发(15-26)-JUC集合-ConcurrentLinkedQueue详解 #### 一、ConcurrentLinkedQueue概述 `ConcurrentLinkedQueue`是Java实用工具包(J.U.C)中的一个高性能线程安全队列,主要用于解决多线程环境下...

    java多线程与高并发视频

    java多线程与高并发java多线程与高并发java多线程与高并发

    Java 多线程与并发(14-26)-JUC集合- CopyOnWriteArrayList详解.pdf

    ### Java多线程与并发(14-26)-JUC集合-CopyOnWriteArrayList详解 #### 一、概述 `CopyOnWriteArrayList`是一种线程安全的集合类,它是`ArrayList`的一种特殊版本,主要通过复制底层数组的方式来保证线程安全性。...

    Java 多线程与并发(8-26)-JUC原子类- CAS, Unsafe和原子类详解.pdf

    Java多线程与并发处理是Java编程中的高级话题,涉及到JUC(java.util.concurrent)包中的原子类、CAS(Compare-And-Swap)机制、Unsafe类以及多线程并发的无锁方案和线程安全的实现方法。 CAS是一种无锁的同步机制...

    Java 多线程与并发(13-26)-JUC集合- ConcurrentHashMap详解.pdf

    【Java 多线程与并发】并发集合类`ConcurrentHashMap`是Java程序设计中一个重要的工具,尤其在高并发场景下,它提供了高效的线程安全。`ConcurrentHashMap`在JDK 1.7和1.8中有着显著的区别。 在JDK 1.7中,`...

    java多线程和并发.pdf

    Java多线程与并发编程是Java语言中用于处理多任务执行的关键技术,它能够帮助开发者设计出能够有效应对高并发请求的应用程序。在现代的线上(Online)和离线(Offline)应用中,合理利用多线程技术可以大幅提高系统...

    java多线程并发

    #### 一、Java多线程并发简介 在现代软件开发中,特别是在Java这样的主流编程语言中,多线程并发技术是提高程序执行效率、优化资源利用的关键手段之一。本篇文章将深入探讨Java中的多线程并发机制,并通过具体的...

    笔记_张孝祥_Java多线程与并发库高级应用

    张孝祥Java多线程与并发库高级应用学习笔记,很经典的学习多线程和并发的资料。张孝祥Java多线程讲义笔记由张孝祥亲自整理,很实用的。

Global site tag (gtag.js) - Google Analytics