我正在实现请求实例的 FIFO 队列(为速度而预先分配的请求对象),并开始使用 add 方法上的“同步”关键字。该方法很短(检查固定大小缓冲区中是否有空间,然后将值添加到数组)。使用visualVM,线程似乎比我喜欢的更频繁地阻塞(准确地说是“监视器”)。因此,我将代码转换为使用 AtomicInteger 值来跟踪当前大小,然后在 while 循环中使用 compareAndSet()(就像 AtomicInteger 在内部对诸如 incrementAndGet() 之类的方法所做的那样)。代码现在看起来更长了。
我想知道的是,使用同步和较短的代码与没有同步关键字的较长代码相比,性能开销是多少(所以永远不应该阻塞锁)。
这是带有 synchronized 关键字的旧 get 方法:
public synchronized Request get()
{
if (head == tail)
{
return null;
}
Request r = requests[head];
head = (head + 1) % requests.length;
return r;
}
这是没有 synchronized 关键字的新 get 方法:
public Request get()
{
while (true)
{
int current = size.get();
if (current <= 0)
{
return null;
}
if (size.compareAndSet(current, current - 1))
{
break;
}
}
while (true)
{
int current = head.get();
int nextHead = (current + 1) % requests.length;
if (head.compareAndSet(current, nextHead))
{
return requests[current];
}
}
}
我的猜测是 synchronized 关键字更糟,因为即使代码更短,也有阻塞锁的风险(可能导致线程上下文切换等)。
谢谢!