使用 java 信号量作为两个 Runnable 类 之间的锁

Using java semaphores as locks between two Runnable classes

我有三个对象,它们是实现 Runnable 接口的两个不同 classes 的实例。其中一个对象更改了其他两个对象的计数器,但我想确保整个更新操作不会被其他线程中断(即我想为我的关键部分使用锁)。

在下面的代码中(这是对实际代码的说明,不是它本身),我想确保关键部分中的代码在没有任何中断的情况下执行。

我的一个想法是在 Worker class 中定义一个二进制信号量 m,并用 [=17 包围每个涉及 valueoperations 的操作=] 后跟 m.release()。但是,在 'Runner' class 中,我有一个对 incrementValue() 的调用,如果我用 acquire()/release() 调用包围 CS 而我在 incrementValue() 中有相同的东西,这没有意义。

我对应该将信号量放在哪里以实现互斥感到有点困惑。

谢谢

class Worker implements Runnable{
    int value;
    int operations;
    // Semaphore m = new Semaphore(1);
    ...
    ...
    void incrementValue(int n){
        // m.acquire() here??
        this.operations++;
        this.value += n;
        // m.release() here??
    }
    ...
    @Override
    public void run(){
        ...
        this.operations++;
        this.value = getRandomNum(); 
        ...
    }
}

class Runner implements Runnable {
    Worker a, b;
    ...
    ...
    @Override
    public void run(){
        ...
        // Start of the CS
        // a.m.acquire() here?
        // b.m.acquire() here?
        a.incrementValue(x);
        System.out.println("Value in WorkerA incremented by " + x);
        b.incrementValue(y);
        System.out.println("Value in WorkerB incremented by " + y);
        // a.m.release() here?
        // b.m.release() here?
        // end of the CS
        ...
    }
    ...
}

听起来您面临的问题与 ReentrantLock 旨在解决的问题相同。 ReentrantLock 让你这样做:

final ReentrantLock m = new ReentrantLock();

void foo() {
    m.lock();
    doFooStuff();
    m.unlock();
}

void bar() {
    m.lock();
    foo();
    doAdditionalBarStuff();
    m.unlock();
}

lock() 调用检查调用线程是否已经拥有锁。如果调用者没有,那么它首先获取锁,必要时等待,最后,在它 returns 之前它设置一个 count 变量为 1.

来自同一线程的后续 lock() 调用将看到线程已经拥有锁,它们将简单地增加计数器和 return.

unlock()调用递减计数器,只有当计数为零时才释放锁。