使用 java 信号量作为两个 Runnable 类 之间的锁
Using java semaphores as locks between two Runnable classes
我有三个对象,它们是实现 Runnable
接口的两个不同 classes 的实例。其中一个对象更改了其他两个对象的计数器,但我想确保整个更新操作不会被其他线程中断(即我想为我的关键部分使用锁)。
在下面的代码中(这是对实际代码的说明,不是它本身),我想确保关键部分中的代码在没有任何中断的情况下执行。
我的一个想法是在 Worker
class 中定义一个二进制信号量 m,并用 [=17 包围每个涉及 value
和 operations
的操作=] 后跟 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()
调用递减计数器,只有当计数为零时才释放锁。
我有三个对象,它们是实现 Runnable
接口的两个不同 classes 的实例。其中一个对象更改了其他两个对象的计数器,但我想确保整个更新操作不会被其他线程中断(即我想为我的关键部分使用锁)。
在下面的代码中(这是对实际代码的说明,不是它本身),我想确保关键部分中的代码在没有任何中断的情况下执行。
我的一个想法是在 Worker
class 中定义一个二进制信号量 m,并用 [=17 包围每个涉及 value
和 operations
的操作=] 后跟 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()
调用递减计数器,只有当计数为零时才释放锁。