Java中使用双计数器进行同步
我有一个奇怪的同步架构,我正在寻找一个优雅的解决方案。我已经有了一个解决方案,但我不能说它的有效性,而且它也有点难看。所以这就是问题,希望有人可以帮助我。
有 2 组可以启动和运行的任务。每个任务都有自己的线程。这两组都从一个负责同步部分的超类扩展而来。为了简单起见,我将这两个组称为 A 组和 B 组。
条件:
如果只有B组任务在运行,那么它们可以同时运行,并且互不干扰。
如果启动 A 组任务*,则 B 组任务的构造函数应该失败并出现异常。即使 A 组任务已在运行,也可以创建任意数量的 A 组任务
在所有当前 B 组任务完成之前,A 组任务无法执行。 (* 来自上面)
一次只能运行 1 个 A 组任务。他们必须排队。 (只要前面的条件仍然适用,可以选择在两个 A 组任务运行之间阻止 B 组任务)
我相信我的方法有效,但我不喜欢它的工作方式,因为它有许多不同的同步点使用,以及我在等待柜台时睡觉的事实。无论如何,代码在下面
public abstract class LockableTask<Params> extends AsyncTask {
private final boolean groupA;
private static Boolean locked = false;
private static final Semaphore semLock = new Semaphore(1);
private static int count = 0;
public LockableTask(boolean groupA) {
this.groupA = groupA;
synchronized (locked) {
if (locked && !groupA) {
throw new InputException("We are locked, please wait");
}
}
}
@Override
protected final AsyncReturn doInBackground(Params... params) {
if (!groupA) {
synchronized (locked) {
count++;
}
}
try {
if (groupA) {
semLock.acquireUninterruptibly();
synchronized (locked) {
locked = true;
}
while (true) {
synchronized (locked) {
if (count == 0) {
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
return runInBackground(params);
} finally {
synchronized (locked) {
if (groupA) {
locked = false;
} else {
count--;
}
}
if (groupA) {
semLock.release();
}
}
}
protected abstract AsyncReturn runInBackground(Params... params);
}
如果有人有更好的解决方案,即使只是好一点,那就太好了
I have a strange synchronization architecture going on and I am looking for an elegant solution. I already had a solution but I cannot say anything about its validity and its also a little ugly. So here is the problem, hopefully someone can help me.
There are 2 groups of tasks that can be started and run. Each task has its own thread. These two groups both extend from one super class that takes care of the synchronization part. I will call these two groups Group A and Group B for simplicity.
Conditions:
If there are only Group B tasks running then they can run at the same time and they do not interfere with each other.
If a Group A task is started* then the constructor for a Group B task should fail with an exception. Any number of Group A tasks can be created even if a Group A task is already running
A Group A task cannot execute until all current Group B tasks have finished. (* from above)
Only 1 Group A task can run at a time. They must be queued. (It is optional to block Group B tasks between the running of the two Group A tasks as long as the previous conditions still apply)
I believe my method works but I do not like the way it works because of the many different synchronization points that it uses, and the fact that I have a sleep while waiting for the counter. Anyway the code is below
public abstract class LockableTask<Params> extends AsyncTask {
private final boolean groupA;
private static Boolean locked = false;
private static final Semaphore semLock = new Semaphore(1);
private static int count = 0;
public LockableTask(boolean groupA) {
this.groupA = groupA;
synchronized (locked) {
if (locked && !groupA) {
throw new InputException("We are locked, please wait");
}
}
}
@Override
protected final AsyncReturn doInBackground(Params... params) {
if (!groupA) {
synchronized (locked) {
count++;
}
}
try {
if (groupA) {
semLock.acquireUninterruptibly();
synchronized (locked) {
locked = true;
}
while (true) {
synchronized (locked) {
if (count == 0) {
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
return runInBackground(params);
} finally {
synchronized (locked) {
if (groupA) {
locked = false;
} else {
count--;
}
}
if (groupA) {
semLock.release();
}
}
}
protected abstract AsyncReturn runInBackground(Params... params);
}
If someone has a nicer solution even if just barely nicer that would be great
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来您想使用
读写锁
。让 A 组的每个任务获取其readLock()
并且 B 组的每个任务获取其writeLock()
。这样,任意数量的 A 组任务可以同时运行,但 B 组中只能运行一个任务(此时其他 A 组任务不能运行)。
Sounds like you want to use a
ReadWriteLock
. Let each task of group A acquire itsreadLock()
and each task of group B acquire itswriteLock()
.This way any number of Group A tasks can run at once, but only ever one task of Group B can run (at which point no other Group A tasks can run).
如果您对同时进行的 B 组任务的数量有上限(即使它非常大),您应该能够使用单个信号量实现您描述的规则。
A 组任务:
B 组任务:
最终结果:当任何 B 组正在运行时,A 无法获得其所需的许可数量。一旦获得许可,任何 B 都无法获得许可证,任何其他 A 也无法获得许可证。
If you have an upper bound on the number of simultaneous Group B tasks (even if it's very large), you should be able to achieve the rules you describe with a single semaphore.
Group A task:
Group B task:
End result: whilst any group B are running, A cannot acquire the number of permits it requires. Once it does, no B can acquire a permit and neither can any other A.