簡體   English   中英

信號量不能避免線程丟失

[英]Semaphores not avoiding thread loss

這是我在這里的第一個問題,所以請多多包涵。

我目前正在 Java 中進行關於多線程和並發的 UNI 分配,我們被要求使用不同的線程鎖定方法實現各種版本的“呼叫中心”,其中一種是信號量。 我將直接進入代碼以顯示我的問題是什么:

制片人Class:

public final class Caller implements Runnable {
    private final CallCenter callCenter;

    public Caller(long id, CallCenter callCenter) {
        this.callCenter = callCenter;
    }

    @Override
    public void run() {
        try {
            callCenter.receive(new Call());
        } catch(Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

消費者 Class:

public final class Operator implements Runnable {
    private final CallCenter callCenter;
    private Call call;

    public Operator(CallCenter callCenter) {
        this.callCenter = callCenter;
    }

    @Override
    public void run() {
        try {
            this.call = callCenter.answer();
        } catch(InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }

    public Call getCall() {
        return this.call;
    }   
}

服務:

import java.util.Queue;
import java.util.concurrent.Semaphore;
import java.util.LinkedList;

public final class BoundedCallCenterSemaphore implements BoundedCallCenter {
    private final Queue<Call> pendingCalls = new LinkedList<Call>();
    private Semaphore semaphore = new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true);

    public void receive(Call call) throws Exception {
        semaphore.acquire();
        pendingCalls.add(call);
    }

    public Call answer() throws InterruptedException {
        semaphore.release();
        return pendingCalls.poll();
    }
}

調用實現:

import java.util.concurrent.atomic.AtomicLong;

public final class Call {
    private static final AtomicLong currentId = new AtomicLong();
    private final long id = currentId.getAndIncrement();

    public long getId() {
        return id;
    }
}

免責聲明

我知道我可能沒有按照預期的方式使用信號量,但是閱讀官方文檔和其他博客/答案根本沒有幫助。 我們有以下限制:只修改Service Class,使用Semaphore解決並且只使用Semaphore.acquire()和Semaphore.receive()避免競速和忙等待,不允許其他方法或線程鎖定結構

實際問題:

我將避免在這里發布我們教授編寫的全部測試,只知道向服務發送了 100 個調用,為簡單起見,每個調用者只調用一次,每個接線員只響應一次。 當在沒有信號量的情況下實現呼叫中心時,您會遇到由 while 循環產生的繁忙等待,並且並發性管理不善,因為如果不同的線程同時操作,某些調用可能會被應答兩次或更多次。 這里的任務是消除繁忙的等待,並確保每個呼叫只接收和應答一次。 我嘗試使用上面報告的信號量,雖然消除了忙碌等待,但一些呼叫最終根本沒有得到應答。 關於我做錯了什么的任何建議? 如何確保每個電話只接聽一次?

最后,我使用了三個信號量。 pendingCalls.size() >= MAX_NUMBER_OF_PENDING_CALLS時,第一個信號量new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true)在阻塞新條目的意義上保護隊列。 第二個信號量new Semaphore(1, true)保護生產者線程,一次只允許一個線程訪問隊列以進行添加操作。 第三個也是最后一個信號量在沒有許可的情況下開始,並等待第一個生產者線程將第一個調用插入緩沖區new Semaphore(0, true)

代碼

public final class BoundedCallCenterSemaphore implements BoundedCallCenter {
    private final LinkedList<Call> pendingCalls = new LinkedList<Call>();
    static Semaphore receiver = new Semaphore(1, true);
    static Semaphore storage = new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true);
    static Semaphore operants = new Semaphore(0, true);

    public void receive(Call call) throws Exception {
        try {
            storage.acquire();
        }
        catch (InterruptedException e)
        {

        }
        try {
            receiver.acquire();
        }
        catch (InterruptedException e)
        {

        }
        synchronized (pendingCalls) {
            pendingCalls.add(call);
            operants.release();
        }
    }

    public Call answer() throws InterruptedException {
        try
        {
            operants.acquire();
        }
        catch (InterruptedException e)
        {

        }
        Call call = null;
        synchronized (pendingCalls) {
            call = pendingCalls.poll();
            storage.release();
            receiver.release();
        }
        return call;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM