使用双计数器在Java中进行同步

Sto*_*yan 0 java multithreading synchronization thread-safety

我有一个奇怪的同步架构,我正在寻找一个优雅的解决方案.我已经有了一个解决方案,但我不能说它的有效性,也有点难看.所以这是问题,希望有人可以帮助我.

有两组任务可以启动和运行.每个任务都有自己的线程.这两个组都从一个负责同步部分的超类扩展.为简单起见,我将这两个组称为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);
}
Run Code Online (Sandbox Code Playgroud)

如果有人有一个更好的解决方案,即使只是勉强更好,那将是伟大的

Joa*_*uer 5

听起来你想要使用ReadWriteLock.让A组的每个任务获得它readLock(),B组的每个任务获得它writeLock().

这样,可以同时运行任意数量的A组任务,但只能运行B组的一个任务(此时不能运行任何其他A组任务).

ReadWriteLock rwLock = getSharedReadWriteLock();
Lock lock = groupA ? rwLock.readLock() : rwLock.writeLock();
lock.lock();
try {
  return runInBackground(params);
} finally {
  lock.unlock();
}
Run Code Online (Sandbox Code Playgroud)