我有以下Java并发问题:
现在直截了当(次优)的实现将是:
class AccessedByManyThreads {
void doActionWithF1() {
foo();
synchronized (this) {
f1();
}
bar();
}
void doActionWithF2() {
baz();
synchronized (this) {
f2();
}
faz();
}
}
这个实现满足要求4.但它没有使用松弛允许的要求2.和3.实际上我需要像ReadWriteLock那样不仅可以共享读锁而且还可以写Write锁。 / p>
所以我的问题:
答案 0 :(得分:0)
我不确定是否有任何Java并发库可以帮助解决此用例。但是,您可以模拟类似于信号量变量的内容来实现此目的:
class AccessedByManyThreads {
private int threadsAccessingF1;
private int threadsAccessingF2;
public AccessedByManyThreads() {
this.threadsAccessingF1 = 0;
this.threadsAccessingF2 = 0;
}
public void doActionWithF1() {
synchronized(this) {
if(threadsAccessingF2 > 0) {
return;
// some function(s) are accessing f2, so return without calling f1()
}
else {
threadsAccessingF1++;
}
}
f1();
synchronized(this) {
threadsAccessingF1--;
}
}
public void doActionWithF2() {
synchronized(this) {
if(threadsAccessingF1 > 0) {
return;
// some function(s) are accessing f1, so return without calling f2()
}
else {
threadsAccessingF2++;
}
}
f2();
synchronized(this) {
threadsAccessingF2--;
}
}
}
答案 1 :(得分:0)
我认为没有标准的图书馆课程可以帮助您开箱即用。
解决方案:
这种情况可与十字路口相媲美,其中f1和f2是两条相交的道路。交通信号灯允许来自f1的流量通过或来自f2,但不允许两者同时通过。我过去遇到过这样的问题,然后构建了这个同步器类:
public class TrafficLight<T> {
private ReentrantLock lock = new ReentrantLock(true);
private Condition switched = lock.newCondition();
private int registered;
private int maxBeforeYield = 20;
private T state;
public void acquire(T t) throws InterruptedException {
lock.lock();
try {
while ((state != null && !state.equals(t)) || maxBeforeYield == 0) {
switched.await();
}
if (state == null) {
state = t;
}
registered++;
maxBeforeYield--;
} finally {
lock.unlock();
}
}
public void release() {
lock.lock();
try {
registered--;
if (registered == 0) {
state = null;
maxBeforeYield = 20;
switched.signalAll();
}
} finally {
lock.unlock();
}
}
}
您创建一个trafficLight,并使尝试调用f1()的方法获取状态&#34; F1&#34;,并尝试调用f2()的方法获取状态&#34; F2&#34; (显然你可以使用其他状态对象。)
如上所述,只要20个或更多线程正在等待不同的状态,该类就会强制切换状态。这基本上相当于将两个方向都设置为红灯,然后在十字路口被清除后将另一个方向设置为绿色。