文档章节

JDK 并发包 - 同步控制

i
 itititit
发布于 2017/08/16 17:34
字数 1114
阅读 3
收藏 0

重入锁:ReentrantLock

相比synchronized, 重入锁有着显示的操作过程;

ReentrantLock lock = new ReentrantLock();

lock.lock();
lock.lock();

try{
    //do something
}finally{
    lock.unlock();
    lock.unlock();
}

一个线程可连续多次获得同一把锁,释放的时候需要释放相同的次数。如果过释放锁的次数过多,会得到异常 IllegalMonitorStateException 

中断响应

lock.lockInterruptibly();
  • 在等待锁的时候,可对中断响应,得到异常 InterruptedException

锁申请等待限时

boolean success = lock.tryLock(5,TimeUnit.SECONDES);
  • 第一个参数为等待时长,第二个参数计时单位
  • 成功获得锁返回true,等待时间内未获得锁返回false。
  • 也可以不带参数,如果锁未被其他线程占用,立即返回true,如果锁被其他线程占用,当前进程不会等待,立即放回false。

公平锁

ReentrantLock lock = new ReentrantLock(true);

公平锁需要一个有序队列,因此实现成本高,性能相对也非常低下。

 

 

条件:Condition

Condition和wait()、notify()方法的功能大致相同。但是 后者与 synchronized 关键字合作使用,而Conditon与重入锁相关联。

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//...
        @Override
        public void run(){
            try{
                lock.lock();
                condition.await();
            } catch( InterruptedException e){
                // 响应中断
            } finally{
                lock.unlock();
            }
        }
//...
    public static void main( String[] args)throws InterruptedException {
        lock.lock();
        condition.signal();
        lock.unlock();
    }

通过Lock 接口 可以生成一个与当前重入锁绑定的Condition实例。

await();
awaitUninterruptibly();
signal();
signalAll();

awaitUninterruptibly() 不会在等待中响应中断。

其他的与Object.wait()、Object.notify()、Object.notifyAll()类似。await()会释放占用的锁。

线程调用的时候,需要持有对应的重入锁。

 

 

信号量:Semaphore

public Semaphore( int permits);//指定permits 个数的线程,可同时访问。
public Semaphore( int permits, boolean fair);// 第二个参数指定是否公平

无论是内部锁synchronized 还是重入锁 ReentrantLock, 一次只允许一个线程访问一个资源。而信号量允许多个线程同时访问某个资源。

public void acquire();
public void  acquireUninterruptibly();
public boolean tryAcquire();
public boolean tryAcquire( long timeout; TimeUnit unit);
public void release();

实例:P84

 

 

读写锁:ReadWriteLock

ReadWriteLock 是JDK5中提供的读写分离锁。读写分离可有效地帮助减少锁竞争,以提升性能。

只有读-读之间不会阻塞,读-写、写-读、写-写 都会阻塞。

    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    Lock readLock = readWriteLock.readLock();
    Lock wrieteLock = readWriteLock.writeLock();

    readlock.lock();
    readlock.unlock();

 

倒计时锁:CountDownLatch

调用countDownLatch.await()的线程等待,其他任务的完成(调用countDown())。

public class Test implements Runnable{
    static Test demo = new Test();
    static CountDownLatch count = new CountDownLatch(10);// 参数为计数个数

    @Override
    public void run() {
        try{
            Thread.sleep(1000);// 模拟任务
            count.countDown();// 通知CountDownLatch一个线程以及完成
        } catch (InterruptedException e) {
            // sleep 中断
        }
    }

    public static void main(String[] args){
        ExecutorService exec = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            exec.submit(demo);
        }
        try {
            count.await();// 等待所有N个线程调用了countDown()
        } catch (InterruptedException e) {
            // CountDownLatch.await() 中断
        }
    }
}

 

 

循环栅栏:CyclicBarrier

public class Test implements Runnable{

    static Test demo = new Test();
    static CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
        @Override
        public void run() {
            System.out.println("本次循环完毕!");
        }
    });

    @Override
    public void run() {
        try {
            System.out.println("正在等待的线程数:" + barrier.getNumberWaiting());
            barrier.await();
            System.out.println("第一个循环完成!");
            barrier.await();
            System.out.println("第二个循环完成!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(demo).start();
            Thread.sleep(1000);
        }
    }
}
  • 当调用N次 barrier.await()后,计数器完成一次计数,并执行第二参数Runnable(最后一个调用await()的线程会直接在本线程中调用run()方法,然后调用signalAll()唤醒前面等待的线程 )。
  • CyclicBarriar 可能抛出两个异常:InterruptedException 和 其特有的BrokenBarrierException,表示当前的CyclicBarrier已经损坏了,在执行就没有意义了。比如其中一个调用barrier.await()的线程被中断了,那么其他调用barrier.await()的线程再继续等待就徒劳无功了。

 

 

线程阻塞工具:LockSupport

让调用LockSupport.park() 的线程阻塞,线程状态为WAITING,它不需要先获得某个对象的锁,也不会抛出InterruptedException

unpark()唤醒线程,不会因unpark()在park() 之前调用而永久挂起。

park();
parkNanos();
parkUntil();
park(Object);
unpark();

unpark函数为线程提供“许可(permit)”,线程调用park函数则等待“许可”。这个有点像信号量,但是这个“许可”是不能叠加的,“许可”是一次性的

此处个人理解为:线程的许可初始是不可用的,当先调用park()时,当前线程等待许可可用,调用unpark()使许可可用后,等待的线程继续执行;当先调用unpark()时,将不可用的许可变为可用,后续调用park()时,检测到许可可用,则立即直接返回,继续执行。 

 

© 著作权归作者所有

i
粉丝 0
博文 24
码字总数 15531
作品 0
私信 提问
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
722
1
[高并发Java 七] 并发设计模式

什么是设计模式 在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题 ,所提出的解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在1990年代从建...

Hosee
2016/02/14
9.4K
1
并发编程源码分析一之Log接口

并发编程实践部分源码使用github里面部分开源框架源码,重新整理,如有错误或版权问题,请指出指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk 模...

Hi徐敏
2015/11/30
184
0
java多线程:jdk并发包的总结(转载)

转载地址:http://blog.csdn.net/yangbutao/article/details/8479520 1、java 高并发包所采用的几个机制(CAS,volatile,抽象队列同步) CAS(乐观操作),jdk5以前采用synchronized,对共享区...

无信不立
2016/08/25
0
0
[高并发Java 九] 锁的优化和注意事项

锁优化的思路和方法 在[高并发Java 一] 前言中有提到并发的级别。 一旦用到锁,就说明这是阻塞式的,所以在并发度上一般来说都会比无锁的情况低一点。 这里提到的锁优化,是指在阻塞式的情况...

Hosee
2016/02/16
8.5K
0

没有更多内容

加载失败,请刷新页面

加载更多

框架和库的区别

框架和库的区别 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目。 node 中的 express; 库(插件):提供某一个小功能,对项目的侵入性较小...

庭前云落
5分钟前
2
1
基于 Dawn 进行多工程管理

1. 简述 当一个项目中子工程较多时,就会面临「单仓库(Monorepo)」还是「多仓库(Multirepo)」管理的问题。当然两个方式各有优缺点,而我们选择多工程单 Repo 时,能够带来一些管理上的简...

阿里云官方博客
6分钟前
1
0
Joomla 4具有可自定义的HTML电子邮件模板

Joomla 4大约每个月都会发布一个Alpha版本。上个月,我们得到了一个新的管理模板。 Joomla 4的最新版本是Alpha 12。 该版本的主要新特性是可定制的电子邮件模板。您将能够控制从您的网站发送...

六艺网络专注于Joomla
9分钟前
1
0
Idea配置

配置文件idea64.exe.vmoptions -Xms128m, 16 G 内存的机器可尝试设置为 -Xms512m (设置初始的内存数,增加该值可以提高 Java 程序的启动速度。 ) -Xmx750m, 16 G 内存的机器可尝试设置为 ...

行者终成事
11分钟前
2
0
大小仅1MB!超轻量级的人脸识别模型火爆Github

项目地址:https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB 近日,用户Linzaer在Github上开源了一款适用于边缘计算设备、移动端设备以及 PC 的超轻量级通用人脸检测...

编程资源库
13分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部