我已经尝试了一段时间内嵌锁和java.util.concurrent.ReentrantLock之间的区别。我发现了很奇怪的事。考虑以下代码:
public class WriteOnceRunAnywhere {
private static long counter = 0;
public static void main(String[] args) throws InterruptedException {
final int numThreads = 2;
final int numIterations = Integer.MAX_VALUE;
Runnable inc = new Runnable() {
public void run() {
for (int i = 0; i < numIterations; i++) {
increment();
if (i % 10000000 == 0)
System.out.println(Thread.currentThread().getName());
}
}
};
for (int i = 0; i < numThreads; i++)
new Thread(inc).start();
}
public static synchronized void increment() {
counter++;
}
}简单的事,没有花哨的东西。对吗?正好破了!很可能当你运行它的时候,它不会结束。在线程之间进行一些乒乓之后,您将看到只有一个线程在实际运行。另一个永远挂着:
线程-1线程-2线程-1线程-2线程-1.线程-2线程-2线程-2.
之后,java进程就不能接受jvisualvm连接。CPU负载下降,并持续保持在1.0%左右。
Mac 10.7.2 (11C74),2.53 GHz Intel Core i5
java版本"1.6.0_29“Java(TM) SE运行时环境(build 1.6.0_29-b11-402-11M3527) Java HotSpot(TM) 64位服务器VM (build 20.4-b02-402,混合模式)
有人能告诉我这里到底发生了什么吗?
UPD看起来该bug将在1.6.30 see中修复。
发布于 2012-01-27 18:48:33
看起来您正在观察MacOS7JDK1.6中存在的一个bug。您可以看到同样的问题发生在这里:
http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008778.html
你可能想从一开始就读到
http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008759.html
最后,对于Open 7似乎有一个解决方案。
http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008789.html
长话短说。它只会在JDK 1.6_14 (或更大的< JDK 7)和Max OS 7中失败。它们的测试和您正在看到的结果非常相似。
我猜你甚至不能得到一个j堆栈或加载j控制台?
发布于 2012-01-27 18:27:33
尝试关闭-XX:-UseBiasedLocking,它可能是ping-pongs,直到代码被优化(尝试-XX:+PrintCompilation,然后它有效地确定如果只有一个线程保存锁,程序运行速度就会更快)。例如,同步被有效地移出循环之外。
当您使用多个线程来做一些比单线程更快的事情时,您会经常看到这种行为。
您可以让每个线程交替地增加值,也可以让一个循环运行,直到它停止为止(在Integer.MAX_VALUE),然后再运行第二个循环。
public class CountingWithThreads {
static long count1 = 0;
static long count2 = 0;
public static void main(String... args) throws InterruptedException {
long start1 = System.nanoTime();
Thread t1a = new Thread(new CountsSingleThreaded(Integer.MAX_VALUE));
Thread t1b = new Thread(new CountsSingleThreaded(Integer.MAX_VALUE));
t1a.start();
t1b.start();
t1a.join();
t1b.join();
long time1 = System.nanoTime() - start1;
System.out.printf("Single threaded, took %.1f second to count to %,d%n", time1 / 1e9, count1);
long start2 = System.nanoTime();
Thread t2a = new Thread(new CountsAlternatively(true, 1000000));
Thread t2b = new Thread(new CountsAlternatively(false, 1000000));
t2a.start();
t2b.start();
t2a.join();
t2b.join();
long time2 = System.nanoTime() - start2;
System.out.printf("Alternating multi-threaded took %.1f second to count to %,d%n", time2 / 1e9, count2);
}
static class CountsSingleThreaded implements Runnable {
private final long maxValue;
CountsSingleThreaded(long maxValue) {
this.maxValue = maxValue;
}
public void run() {
synchronized (CountingWithThreads.class) {
for (long i = 0; i < maxValue; i++) {
count1++;
}
}
}
}
static class CountsAlternatively implements Runnable {
private final boolean even;
private final long maximum;
CountsAlternatively(boolean even, long maximum) {
this.even = even;
this.maximum = maximum;
}
public void run() {
try {
synchronized (CountingWithThreads.class) {
while (count2 < maximum)
if (((count2 & 1) == 0) == even) {
count2++;
CountingWithThreads.class.notify();
} else {
CountingWithThreads.class.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}版画
Single threaded, took 2.3 second to count to 4,294,967,294
Alternating multi-threaded took 3.4 second to count to 1,000,000一次运行一个线程来完成一个线程是最有效的。如果您强制严格交替的计数器(最极端的例子多线程),它是超过1000倍的慢。
发布于 2012-01-31 22:40:56
我们有一个开发人员预览,它修复了一些低级别的同步问题。如果您在Mac JDK6上有同步问题,请用您的代码测试这个预览,看看它是否解决了硬件上的问题。谢谢。
开发人员预览是实时的:https://developer.apple.com/downloads/index.action?name=Java%20for%20Mac%20OS%20X%20Developer%20Preview。
https://stackoverflow.com/questions/9038169
复制相似问题