`
hyxw5890
  • 浏览: 35267 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

深入Java多线程和并发编程之Semaphore

 
阅读更多
以前在学操作系统时就接触过信号量(Semaphore['seməfɔ:])的概念,指的是多线程环境下保证一个或多个关键代码段不被并发调用。

举一个简单的例子可以帮助理解:比如车库的容量是有限的、同一时刻只能停100辆车、超过了100辆、其他的车辆就只能等待了。

在Jdk的java.util.concurrent包中已经实现了一个Semaphore类、我们可以直接拿来用、不需要再重复制造轮子了。

该类有如下一些特点:
1、Semaphore是带有Counting、相当于维护了一定数量的通行证、如上面举的例子里面的100辆车
2、该类的acquire方法是为了申请通行证的、该方法可能会Block(这里并没有使用synchronization、因为否则的话release也没法执行)、就是当通行证全部被申请完了之后。而对应的release方法则是释放通行证的、这样该方法执行后可能会让原来Block的acquire方法得以继续执行。
3、上面2的执行过程中其实并没有类似于通行证这样的对象、Semaphore只是维护了一个许可的计数器。
4、如果Semaphore的计数器为1(又叫binary Semaphore)的话则相当于一个互斥锁

实际应用中、对象池和线程池都有使用如此的方式控制线程的使用量。


下面是一个代码示例:

package com.alibaba.plouto.test.mock;

import java.util.concurrent.Semaphore;

public class TestSemaphore {
    public static CarWarehouse carWarehouse = new CarWarehouse();

    public static void main(String args[]) {
        for (int i = 0; i <= 10; i++) {
            new Thread(new Producer(i)).start();
            new Thread(new Consumer()).start();
        }
    }

    static class CarWarehouse {
        final int       MAX_PERMITS = 5;
        final Semaphore permits     = new Semaphore(MAX_PERMITS);
        final Semaphore mutex       = new Semaphore(1);
        // 库存容量  
        final Object[]  carWaits    = new Object[MAX_PERMITS];
        int             count;

        public void put(Object x) throws InterruptedException {
            permits.acquire();
            for (int i = 0; i < MAX_PERMITS; i++) {
                if (carWaits[i] == null) {
                    //防止两辆车正好进同一个车位(当车库没满时、可以同时进多辆车)
                    mutex.acquire();
                    //通过Double Check防止细粒度的并发问题
                    if (carWaits[i] == null) {
                        carWaits[i] = x;
                        System.out.println("put " + carWaits[i]);
                        //停到了车位、释放互斥锁
                        mutex.release();
                        break;
                    } else {
                        //发现该车位满了、也需要释放互斥锁、继续寻找下一个位置
                        mutex.release();
                    }
                }
            }
        }

        public void take() throws InterruptedException {
            int i = 0;
            while (true) {
                if (carWaits[i] != null) {
                    mutex.acquire();
                    if (carWaits[i] != null) {
                        System.out.println("take " + carWaits[i]);
                        carWaits[i] = null;
                        permits.release();
                        mutex.release();
                        break;
                    } else {
                        mutex.release();
                    }
                }
                i++;
                if (i == MAX_PERMITS)
                    i = 0;
            }
        }
    }

    static class Producer implements Runnable {
        private String car;

        public Producer(int i) {
            car = "car" + i;
        }

        public void run() {
            try {
                carWarehouse.put(car);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Consumer implements Runnable {

        public void run() {
            try {
                carWarehouse.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

分享到:
评论

相关推荐

    JAVA高质量并发详解,多线程并发深入讲解

    本书全面解析了Java并发编程的核心概念、原理和实践,帮助读者深入理解多线程并发编程的精髓,提升编程能力和系统性能。 书中首先介绍了并发编程的基础知识,包括线程的基本概念、线程的生命周期、线程安全等问题。...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │ 高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │ 高并发编程第一阶段07讲、策略模式在Thread和Runnable...

    Java多线程之并发工具类

     主要参考资料:java并发编程的艺术、Java并发——同步工具类  二、CountDownLatch(同步倒数计数器)–不仅仅用于多线程  1.作用:允许一个或多个线程等待其他线程完成操作。  CountDownLatch的构造函数...

    92道Java多线程与并发面试题含答案(很全)

    Java并发编程的核心概念包括: 线程(Thread):线程是程序执行流的最小单元。一个进程可以有一个或多个线程,每个线程都执行其自己的任务。 进程(Process):进程是操作系统分配资源(如内存)和调度的单位。一个...

    Java并发编程原理与实战

    了解多线程所带来的安全风险.mp4 从线程的优先级看饥饿问题.mp4 从Java字节码的角度看线程安全性问题.mp4 synchronized保证线程安全的原理(理论层面).mp4 synchronized保证线程安全的原理(jvm层面).mp4 单例问题...

    【2018最新最详细】并发多线程教程

    【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...

    龙果 java并发编程原理实战

    龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │ 高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │ 高并发编程第一阶段07讲、策略模式在Thread和Runnable...

    Java 并发编程原理与实战视频

    java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...

    Java并发编程相关技术使用案例

    1、本资源包含并发编程基础知识的使用案例,包括:线程创建、Synchronized和Reentrantlock锁的使用、线程安全问题演示、Condition的应用、CountDownLatch的应用、Cyclicbarrier的应用、Semaphore的应用、线程池的...

    龙果java并发编程完整视频

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    Java并发编程实战

    Java并发编程实战 本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及...

    JUC多线程学习个人笔记

    JUC(Java Util Concurrent)是Java中用于并发编程的工具包,提供了一组接口和类,用于处理多线程和并发操作。JUC提供了一些常用的并发编程模式和工具,如线程池、并发集合、原子操作等。 JUC的主要特点包括: ...

    并发编程笔记20190526.docx

    1. Java程序天生就是多线程的 7 2. 线程的启动与中止 7 3. 对Java里的线程再多一点点认识 8 三、线程间的共享和协作 9 1. 线程间的共享 9 2. ThreadLocal辨析 11 3. 线程间的协作 19 4. 面试题 21 第二章 线程的并发...

    Java并发编程(学习笔记).xmind

    Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...

    java并发编程

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用 CountDownLatch、CyclicBarrier、Semaphore这些线程协作工具类是基于AQS的,看完这篇博客后可以去看下面这篇博客,了解它们是如何实现的。 Java并发...

    java并发编程-AQS和JUC实战

    之所以称之为重⼊锁,就是⼀个线程允许反复进⼊。当然,这⾥的反复仅仅局限于⼀个线程;如 果同⼀个线程多次获锁,那么在释放锁的时候,也必须释放相同次数。如果释放锁的次数多,那么 会得到⼀个java.lang....

Global site tag (gtag.js) - Google Analytics