JAVA同步锁Semaphore

简介: JAVA同步锁Semaphore

Semaphore(/ˈseməfɔːr/)介绍

Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于AbstractQueuedSynchronizer实现的。

Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获取信号量实现。大小为n(n>0)的信号量可以实现限流的功能,它可以实现只能有n个线程同时获取信号量

PV操作

PV操作是操作系统一种实现进程互斥与同步的有效方法。 PV操作与信号量(S)的处理相关,P表示通过的意思,V表示释放的意思。用PV操作来管理共享资源时,首先要确保PV操作自身执行的正确性。

P操作的主要动作是:

①S减1;

②若S减1后仍大于或等于0,则进程继续执行;

③若S减1后小于0,则该进程被阻塞后放入等待该信号量的等待队列中,然后转进程调度。

V操作的主要动作是:

①S加1;

②若相加后结果大于0,则进程继续执行;

③若相加后结果小于或等于0,则从该信号的等待队列中释放一个等待进程,然后再返回原进程继续执行或转进程调度。

Semaphore 常用方法

构造器

  • permits 表示许可证的数量(资源数)
  • fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最久的线程

常用方法

public void acquire() throws InterruptedException 
public boolean tryAcquire() 
public void release() 
public int availablePermits() 
public final int getQueueLength() 
public final boolean hasQueuedThreads() 
protected void reducePermits(int reduction) 
protected Collection<Thread> getQueuedThreads()
  • acquire() 表示阻塞并获取许可
  • tryAcquire() 方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻塞
  • release() 表示释放许可
  • int availablePermits():返回此信号量中当前可用的许可证数。
  • int getQueueLength():返回正在等待获取许可证的线程数。
  • boolean hasQueuedThreads():是否有线程正在等待获取许可证。
  • void reducePermit(int reduction):减少 reduction 个许可证
  • Collection getQueuedThreads():返回所有等待获取许可证的线程集合

应用场景

可以用于做流量控制,确保同一时间最多只有指定数量的线程在工作,特别是公用资源有限的应用场景

限流

// 声明3个窗口  state:  资源数
Semaphore windows = new Semaphore(3);
for (int i = 0; i < 5; i++) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                // 占用窗口    加锁
                windows.acquire();
                System.out.println(Thread.currentThread().getName() + ": 开始买票");
                //模拟买票流程
                Thread.sleep(5000);
                System.out.println(Thread.currentThread().getName() + ": 购票成功");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放窗口
                windows.release();
            }
        }
    }).start();
}

Semaphore 原理

   创建Semaphore对象将state设置为指定值。调用acquire方法使用CAS将state减掉指定值,同时判断减掉后的值是否大于0,如果小于0,则将当前线程挂起并加入阻塞队列。调用release方法将state加上指定值,未成功前一直死循环,直到成功,然后唤醒等待队列中的线程。

相关文章
|
2月前
|
Java API
JAVA同步锁CountDownLatch
JAVA同步锁CountDownLatch
|
3月前
|
Java
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
|
7月前
|
Java 编译器 C++
Java同步锁Synchronized底层源码和原理剖析
Java同步锁Synchronized底层源码和原理剖析
74 0
|
10月前
|
Java 程序员
Java中的Semaphore和CountDownLatch这两个工具类的使用方法和实际应用场景
Java中的Semaphore和CountDownLatch这两个工具类的使用方法和实际应用场景
171 0
|
11月前
|
Java
Java Review - 并发编程_ 信号量Semaphore原理&源码剖析
Java Review - 并发编程_ 信号量Semaphore原理&源码剖析
74 0
|
11月前
|
Java
Java多线程:Semaphore
Java多线程:Semaphore
82 0
|
安全 Java
Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的。
111 0
|
Java
【Java技术指南】「原理剖析」Semaphore工作原理分析
【Java技术指南】「原理剖析」Semaphore工作原理分析
73 0
|
Java Windows
Java 并发编程之Semaphore详解
Java 并发编程之Semaphore详解
|
Java
JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
利用实例介绍JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
119 0
JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别