Java中的信號量Semaphore


信號量的實現模型一般包括:1個計數器、1個等待隊列、3個方法(需要保證原子性)

Semaphore 實現的偽代碼(JDK 中 Semaphore 是基於 AbstractQueuedSynchronizer 實現,可以指定是否公平):

class Semaphore{
    //計數器
    int count;
    
    //等待隊列
    Queue queue;
    
    //初始化
    Semaphore(int c){
        this.count=c;
    }
    
    //獲取許可證
    void acquire(){
        count--;
        if(count<0){
            //將當前線程插入等待隊列
            //阻塞當前線程
        }
    }
    
    //獲取許可證
    void release(){
        count++;
        if(count<=0) {
            //移除等待隊列中的某個線程
            //喚醒某個線程
        }
    }
}

 

 

使用信號量實現互斥鎖效果:

package constxiong.interview;

import java.util.concurrent.Semaphore;

/**
 * 測試使用信號量實現鎖的效果
 * @author ConstXiong
 * @date 2019-12-18 14:18:47
 */
public class TestSemaphore {

    private static int count;
    
    private static Semaphore semaphore = new Semaphore(1); 
    
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                add();
                System.out.println(count);
            }).start();
        }
    }
    
    private static void add() {
        try {
            semaphore.acquire();
            Thread.sleep(100);
            count++;
        } catch(InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
    
}

 

 

除了能實現互斥鎖,信號量還可以做到允許多個線程訪問同一個臨界區,這是它與互斥鎖一個較大的區別點。

將代碼進行修改,實現限流功能:

package constxiong.interview;

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 測試使用信號量實現限流的效果
 * @author ConstXiong
 * @date 2019-12-18 14:18:47
 */
public class TestSemaphore {
    
    private static AtomicInteger acount = new AtomicInteger(0);
    
    private static Semaphore semaphore = new Semaphore(10); 
    
    public static void main(String[] args) {
        testAddAtomic();
    }
    
    /**
     * 測試允許十個線程並發遞增 acount
     */
    private static void testAddAtomic() {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                System.out.println(addAtomic());
            }).start();
        }
    }
    
    private static int addAtomic() {
        try {
            semaphore.acquire();
            Thread.sleep(100);
            return acount.incrementAndGet();
        } catch(InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
        return -1;
    }
    
}

 

 

在實際的 Java 開發中,信號量的使用相對互斥鎖來說較少,知名度沒那么高,但在其他編程語言中使用較廣。


原文鏈接
 


 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM