我正在学习 Java 多线程,但遇到问题,我无法理解信号量。如何按此顺序执行线程?例如:在 image1 上:第 5 个线程开始运行,然后第 1 个和第 2 个线程完成执行。
图 2:
图 1:
我现在上传图片以便更好地理解。:))
我正在学习 Java 多线程,但遇到问题,我无法理解信号量。如何按此顺序执行线程?例如:在 image1 上:第 5 个线程开始运行,然后第 1 个和第 2 个线程完成执行。
图 2:
图 1:
我现在上传图片以便更好地理解。:))
通常在 Java 中使用互斥体(也称为监视器),它禁止两个或多个线程访问受该互斥体保护的代码区域
该代码区域是使用sychronized
语句定义的
sychronized(mutex) {
// mutual exclusive code begin
// ...
// ...
// mutual exclusive code end
}
其中互斥锁定义为例如:
Object mutex = new Object();
为了防止任务启动,您需要在 java.util.concurrency 包中定义的高级技术,例如屏障。
但首先要让自己对这种synchronized
说法感到满意。
如果您认为您会经常在 java 中使用多线程,您可能需要阅读
《Java 并发实践》
使用同步,以便每个线程一次进入该方法或代码的那部分。如果你想
public class CountingSemaphore {
private int value = 0;
private int waitCount = 0;
private int notifyCount = 0;
public CountingSemaphore(int initial) {
if (initial > 0) {
value = initial;
}
}
public synchronized void waitForNotify() {
if (value <= waitCount) {
waitCount++;
try {
do {
wait();
} while (notifyCount == 0);
} catch (InterruptedException e) {
notify();
} finally {
waitCount--;
}
notifyCount--;
}
value--;
}
public synchronized void notifyToWakeup() {
value++;
if (waitCount > notifyCount) {
notifyCount++;
notify();
}
}
}
这是计数信号量的实现。它维护计数器变量“value”、“waitCount”和“notifyCount”。如果 value 小于 waitCount 并且 notifyCount 为空,这会使线程等待。
您可以使用 Java 计数信号量。从概念上讲,信号量维护一组许可。如有必要,每个 acquire() 都会阻塞,直到获得许可,然后再接受它。每个 release() 添加一个许可,可能会释放一个阻塞的获取者。但是,没有使用实际的许可对象;Semaphore 只是对可用数量进行计数并采取相应措施。
信号量通常用于限制可以访问某些(物理或逻辑)资源的线程数。例如,这是一个使用信号量来控制对项目池的访问的类:
class Pool {
private static final MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
在获取项目之前,每个线程必须从信号量中获取许可,以保证项目可供使用。当线程完成该项目时,它会返回到池中,并向信号量返回一个许可,允许另一个线程获取该项目。请注意,调用 acquire() 时不会持有同步锁,因为这会阻止项目返回到池中。信号量封装了限制对池的访问所需的同步,与维护池本身一致性所需的任何同步分开。
初始化为 1 的信号量,并且使用时最多只有一个可用的许可,可以用作互斥锁。这通常被称为二进制信号量,因为它只有两种状态:一个许可可用,或零个许可可用。当以这种方式使用时,二进制信号量具有属性(与许多 Lock 实现不同),“锁”可以由所有者以外的线程释放(因为信号量没有所有权的概念)。这在一些专门的上下文中很有用,例如死锁恢复。