并发编程5-同步器

Synchronizer

控制多个线程的流程,比如线程执行到某一个点的时候是等待还是通过。 JDK中自带了信号量,关卡,闭锁

闭锁CoutDownLatch

达到最终状态前是关闭的,所有线程在此阻塞,  达到最终状态后开放,并且不可以再修改,所有线程进入可运行状态。

很适合,等待初始化, 等待依赖等等场景。

如:

/**
 * 设置countDownLatch的初始值,
 * 用await()来等待
 * 用countDown来倒计时 --初始值
 * 当初始值为0时await()等待被notify
 */
public class TestLatch {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(1);
        final String[] datas = new String[3];
        new Thread(){
            @Override
            public void run() {
                try {
                    System.out.println("等待初始化");
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("初始化完成。开始执行");
                for (String data : datas) {
                    System.out.println(data);
                }
            }
        }.start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        datas[0] = "我";
        datas[1] = "爱";
        datas[2] = "你";
        System.out.println("初始化完成");
        latch.countDown();
    }
}

信号量 

适用于连接池等场景

/**
 * 创建一个含有固定许可数的信号量
 * 线程用acquire()标记获得了一个许可,切许可-1,当许可为0时等待,
 * 用release来释放许可,许可+1,其他等待的线程可以获得许可了。
 */
public class TestSemaphore {
    public static void main(String[] args) {
        final Semaphore semaphore = new Semaphore(5);

        for (int i = 0; i < 20; i++) {
            new Thread("thread" + i){
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + "正在执行");
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    semaphore.release();;
                }
            }.start();
        }
    }
}

关卡

与闭锁不同的是,闭锁等待状态,而关卡是等待线程。

特别适用于把一个计算拆分成多个进行计算,最后再进行整合。

/**
 * 关卡
 * 定义所有线程都到关卡之后的行为及关卡中包含的线程数量
 *
 * 各个线程使用await方法来表示已经到这个关卡等着了
 *
 * 当指定数目的线程等着了,那么就开放关卡, 所有线程及刚才定义的行为都继续执行
 */
public class TestBarrier {
    public static void main(String[] args) {
        final String[] friends = new String[]{"1", "2", "3"};
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                System.out.println("出发");
            }
        });

        for (final String friend : friends) {
            new Thread(){
                @Override
                public void run() {
                    System.out.println(friend + "到集合点了");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println(friend + "出发");
                }
            }.start();
        }
    }
}

打印如下:

1到集合点了
3到集合点了
2到集合点了
出发
2出发
3出发
1出发
时间: 2024-09-20 00:13:25

并发编程5-同步器的相关文章

Java并发编程相关面试问题

基础概念 1.什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)? 原子操作(atomic operation)意为"不可被中断的一个或一系列操作" .处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作. 在Java中可以通过锁和循环CAS的方式来实现原子操作. CAS操作--Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作. 原子操作是

推荐阅读Java并发性领域编程最值得一读的力作《JAVA并发编程实践》

我的第一次之给<JAVA并发编程实践>写推荐序英文书名:Java Concurrency in Practice 中文书名:JAVA并发编程实践 这是一本入围17届Jolt大奖的书,虽然最终他没有获奖,但是这只是与政治有关的.:) 推荐序原文如下: http://book.csdn.net/bookfiles/398/10039814644.shtml 在汗牛充栋的 Java 图书堆中,关于并发性的书籍却相当稀少,然而这本书的出现,将极大地弥补了这一方面的空缺.即使并发性编程还没进入到您的 J

《Java线程与并发编程实践》—— 导读

前言 Java线程与并发编程实践 线程和并发工具并非尤物,但是它们是正式应用的重要部分.本书会向你介绍Java 8 Update 60中线程特性以及并发工具的大部分内容. 第1章介绍了类Thread和接口Runnable.你会学习如何创建Thread以及Runnable对象,获取和设置线程状态.启动线程.中断线程,将一条线程插入另外一条线程以及触发线程睡眠. 第2章关注同步.学习后你会解决一些问题,如没有同步就无法解决的竞态条件.你也能学到如何创建同步方法.块,以及如何使用忽略互斥访问的轻量级同

Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock(转)

本文内容主要总结自<Java并发编程的艺术>第5章--Java中的锁.   一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步组建的基础框架.该类主要包括: 1.模式,分为共享和独占. 2.volatile int state,用来表示锁的状态. 3.FIFO双向队列,用来维护等待获取锁的线程. AQS部分代码及说明如下: public abstract class AbstractQueuedSynchronizer exte

《Java并发编程的艺术》-Java并发包中的读写锁及其实现分析

作者:魏鹏  本文是<Java并发编程的艺术>的样章 1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升. 除了保证写操作对读操作的可见性以及并发性的提升之外,读写锁能够简化读写交互场景的编程方式.假设在程序中定义一个共享

《Java并发编程的艺术》一一3.5 锁的内存语义

3.5 锁的内存语义 众所周知,锁可以让临界区互斥执行.这里将介绍锁的另一个同样重要,但常常被忽视的功能:锁的内存语义.3.5.1 锁的释放-获取建立的happens-before关系 锁是Java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 下面是锁释放-获取的示例代码. class MonitorExample { int a = 0; public synchronized void writer() { // 1 a++; //

Java并发编程系列之一:并发机制的底层原理

前言 并发编程的目的是让程序运行更快,但是使用并发并不定会使得程序运行更快,只有当程序的并发数量达到一定的量级的时候才能体现并发编程的优势.所以谈并发编程在高并发量的时候才有意义.虽然目前还没有开发过高并发量的程序,但是学习并发是为了更好理解一些分布式架构.那么当程序的并发量不高,比如是单线程的程序,单线程的执行效率反而比多线程更高.这又是为什么呢?熟悉操作系统的应该知道,CPU是通过给每个线程分配时间片的方式实现多线程的.这样,当CPU从一个任务切换到另一个任务的时候,会保存上一个任务的状态,

并发编程(二):分析Boost对 互斥量和条件变量的封装及实现生产者消费者问题

请阅读上篇文章<并发编程实战: POSIX 使用互斥量和条件变量实现生产者/消费者问题>.当然不阅读亦不影响本篇文章的阅读. Boost的互斥量,条件变量做了很好的封装,因此比"原生的"POSIX mutex,condition variables好用.然后我们会通过分析boost相关源码看一下boost linux是如何对pthread_mutex_t和pthread_cond_t进行的封装. 首先看一下condition_variable_any的具体实现,代码路径:/

Python中利用生成器实现的并发编程

  这篇文章主要介绍了简单介绍Python中利用生成器实现的并发编程,使用yield生成器函数进行多进程编程是Python学习进阶当中的重要知识,需要的朋友可以参考下 我们都知道并发(不是并行)编程目前有四种方式,多进程,多线程,异步,和协程. 多进程编程在python中有类似C的os.fork,当然还有更高层封装的multiprocessing标准库,在之前写过的python高可用程序设计方法中提供了类似nginx中master process和worker process间信号处理的方式,保

《GO并发编程实战》—— 原子操作

声明:本文是<Go并发编程实战>的样章,感谢图灵授权并发编程网站发布样章,禁止以任何形式转载此文. 我们已经知道,原子操作即是进行过程中不能被中断的操作.也就是说,针对某个值的原子操作在被进行的过程当中,CPU绝不会再去进行其它的针对该值的操作.无论这些其它的操作是否为原子操作都会是这样.为了实现这样的严谨性,原子操作仅会由一个独立的CPU指令代表和完成.只有这样才能够在并发环境下保证原子操作的绝对安全. Go语言提供的原子操作都是非侵入式的.它们由标准库代码包sync/atomic中的众多函