2

我有一个线程,它只有在获得对 2 个信号量的独占访问权时才会执行操作。

public void run(){
            boolean a1=false;
            boolean a2=false;
            boolean a3=false;
            while(true){
                try{
                    if(res[1].tryAcquire()==true){
                        a1=true;
                        if((res[2].tryAcquire()==true){
                            a2=true;
                            if(res[3].tryAcquire()==true)){
                                a3=true;
                                System.out.println("Rolled the tobacco");
                            }
                        }   
                    }
                }
                finally{
                    if(a1){
                        a1=false;
                        res[1].release();
                    }
                    if(a2){
                        a2=false;
                        res[2].release();
                    }
                    if(a3){
                        a3=false;
                        res[3].release();
                    }
                }
            }
        }
    }

有没有更好的方法来写这个来确保我们不会扰乱信号量获取计数?有没有办法检查当前线程是否获取了信号量?

4

2 回答 2

2

在 Java 7 中可以尝试一下Closeable。当然必须有更好的解决方案。

public class Region implements Closeable {

    private final Semaphore semaphore;

    public Region(Semaphore semaphore) {
        this.semaphore = semaphore;
        if (!semaphore.tryAcquire()) {
            throw NotAcquiredException(semaphore);
        }
    }

    @Override
    public void close() {
         semaphore.release();
    }
}

public class NotAcquiredException extends Exception { ... }

用法:

    public void run() {
        boolean a1 = false;
        boolean a2 = false;
        boolean a3 = false;
        while (true) {
            try (Closeable r1 = new Region(res[1])) {
                 a1 = true;
                 try (Closeable r2 = new Region(res[2])) {
                     a2 = true;
                     try (Closeable r3 = new Region(res[3])) {
                          a3 = true;
                          System.out.println("Rolled the tobacco");
                     } catch (IOException e) {
                     }
                 } catch (IOException e) {
                 }
            } catch (IOException e) {
            }
       }
于 2013-01-09T07:21:17.223 回答
1

您可以将每个获取分成一个尝试......最后,不是更短,而是摆脱一些变量并使每个锁应该发生的事情变得相当明显。(我将数组更改为从零开始)

public void run(){
    while(true){
        if(res[0].tryAcquire()){
            try {
                if(res[1].tryAcquire()) {
                    try {
                    if(res[2].tryAcquire()){
                        try {
                            System.out.println("Rolled the tobacco");
                        } finally {
                            res[3].release();
                        }
                    }
                    } finally {
                        res[2].release();
                    }                               
                }
            } finally{
                res[1].release();
            }
        }
    }
}

如果您需要获取大量锁或在多个地方执行此操作,那么辅助类可能会很好。至少隐藏了获取和释放信号量的样板代码。

public void run() {
    SemaphoreHelper semaphoreHelper = new SemaphoreHelper(res);
    while (true) {
        try {
            if (semaphoreHelper.aquireAll()) {
                System.out.println("Rolled the tobacco");
            }
        } finally {
            semaphoreHelper.releaseAquired();
        }
    }
}

private static class SemaphoreHelper {

    private final Semaphore[] semaphores;
    private int semaphoreIndex;

    public SemaphoreHelper(Semaphore[] semaphores) {
        this.semaphores = semaphores;
    }

    public void releaseAquired() {
        while (semaphoreIndex > 0) {
            semaphoreIndex--;
            semaphores[semaphoreIndex].release();
        }
    }

    public boolean aquireAll() {
        while (semaphoreIndex < semaphores.length) {
            if (!semaphores[semaphoreIndex].tryAcquire()) {
                return false;
            }
            semaphoreIndex++;
        }
        return true;
    }
}
于 2013-01-09T07:41:15.063 回答