JAVA并发之多线程基础(2)

栏目: Java · 发布时间: 6年前

内容简介:除了我们经常用的使用这个方法就可以在加锁的过程中进行中断,用来保证程序的正常进行下去,避免死锁一直阻塞程序运行。通过上面的方法进行查看底层调用的:
JAVA并发之多线程基础(2)

除了我们经常用的 synchronized 关键字(结合 Objectwait()notify() 使用)之外,还有对应的上篇文章讲到的方法 JAVA并发之多线程基础(1) 之外,我们日常中使用到最多的也就是JUC下面对应的类与方法。

ReentrantLock

ReentrantLock 在JDK1.5之前比 Synchronized 性能好许多,在之后 Synchronized 也进行了修改,使得当下两个在对于线程方面性能相差无几。但是 ReentrantLock 的功能更加丰富,它的特点有:可重入、可中断、可限时、公平锁。

package com.montos.lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo implements Runnable {
	public static ReentrantLock lock = new ReentrantLock();
	public static int k = 0;
	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			lock.lock();
			try {
				k++;
			} finally {
				lock.unlock();
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		ReentrantLockDemo demo = new ReentrantLockDemo();
		Thread t1 = new Thread(demo);
		Thread t2 = new Thread(demo);
		t1.start();
		t2.start();
		t1.join();
		t2.join();
		System.out.println(k);
	}

}
复制代码
  1. 通过这个小的demo可以看到控制台中无论如何执行,输出的值都是2000。这里面就体现了可重入(对于同一把锁进行加锁和释放锁)的特点。

  2. 可中断则在 lockInterruptibly() 这个方法上进行体现。

public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
复制代码

使用这个方法就可以在加锁的过程中进行中断,用来保证程序的正常进行下去,避免死锁一直阻塞程序运行。通过上面的方法进行查看底层调用的:

//以独占模式获取,如果中断将中止。
 public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted()) //测试当前线程是否已中断
            throw new InterruptedException();
        if (!tryAcquire(arg)) //尝试获取arg次锁操作
            doAcquireInterruptibly(arg);//以独占中断模式获取锁操作
    }
复制代码
  1. 可限时操作在 tryLock(long timeout, TimeUnit unit) 方法中体现,目的主要是防止死锁的发生。
public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
复制代码

在使用这个的时候,也要注意在 finally 中也要释放锁,当然在释放之前先判断当前当前线程是否持有锁操作 lock.isHeldByCurrentThread()

  1. 公平锁则在 ReentrantLock 的构造函数中体现出来。所谓公平锁与非公平锁就是线程先来先到和先来不一定拿到锁的情况的。
public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
复制代码

当然非公平锁的性能要比公平锁的性能好很多,公平锁里面还要维护一个队列(AQS)来进行操控公平性。所以说一般没有特殊要求的情况下,默认使用非公平的锁就可以。

Condition

上面讲完重入锁之后,这里在讲解一个与重入锁密切相关的类。他与重入锁之间的关系犹如 synchronizedObjectwait()notify() 一样。也就是说在使用它的情况也要获得当前的锁,才可以进行下面的操作。

package com.montos.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockCondition implements Runnable {
	public static ReentrantLock lock = new ReentrantLock();
	public static Condition condition = lock.newCondition();

	@Override
	public void run() {
		try {
			lock.lock();//拿到对应锁
			condition.await();
			System.out.println("wait is end,going down");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			if (lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		ReentrantLockCondition conditions = new ReentrantLockCondition();
		Thread thread = new Thread(conditions);
		thread.start();
		Thread.sleep(2000);
		lock.lock();
		condition.signal();//只有拿到对应锁上面的监视器才可以执行
		lock.unlock();
	}
}
复制代码

这上面的 Condition 的用法相当于 Object 里面的两个方法一样。总体来说使用重入锁也是看业务场景情况下使用,如果想要上面特点的锁方法,那么使用重入锁就是很好的。不然的话使用 synchronized 关键字就可以完成大多数的业务场景了。


以上所述就是小编给大家介绍的《JAVA并发之多线程基础(2)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

iOS面试之道

iOS面试之道

故胤道长、唐巧 / 电子工业出版社 / 2018-7 / 59.00元

《iOS面试之道》是作者将多年的工作经验和积累,结合具体面试内容总结而成的。 《iOS面试之道》共分为3部分。第1部分为面试准备,详细介绍求职中遇到的基本问题,作者根据其多年的经验,在面试流程、简历投递、复习准备方面给出了完善的参考意见和建议。第2部分为算法知识。算法几乎是各种水平的程序员都要面对的考查内容。该部分采用Swift语言重新审视了多种数据结构和算法原理,可以说是为iOS开发者量身......一起来看看 《iOS面试之道》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具