首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 6 Mac上奇怪的并发行为

Java 6 Mac上奇怪的并发行为
EN

Stack Overflow用户
提问于 2012-01-27 18:23:33
回答 3查看 857关注 0票数 1

我已经尝试了一段时间内嵌锁和java.util.concurrent.ReentrantLock之间的区别。我发现了很奇怪的事。考虑以下代码:

代码语言:javascript
复制
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中修复。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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控制台?

票数 1
EN

Stack Overflow用户

发布于 2012-01-27 18:27:33

尝试关闭-XX:-UseBiasedLocking,它可能是ping-pongs,直到代码被优化(尝试-XX:+PrintCompilation,然后它有效地确定如果只有一个线程保存锁,程序运行速度就会更快)。例如,同步被有效地移出循环之外。

当您使用多个线程来做一些比单线程更快的事情时,您会经常看到这种行为。

您可以让每个线程交替地增加值,也可以让一个循环运行,直到它停止为止(在Integer.MAX_VALUE),然后再运行第二个循环。

代码语言:javascript
复制
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();
            }
        }
    }
}

版画

代码语言:javascript
复制
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倍的慢。

票数 0
EN

Stack Overflow用户

发布于 2012-01-31 22:40:56

我们有一个开发人员预览,它修复了一些低级别的同步问题。如果您在Mac JDK6上有同步问题,请用您的代码测试这个预览,看看它是否解决了硬件上的问题。谢谢。

开发人员预览是实时的:https://developer.apple.com/downloads/index.action?name=Java%20for%20Mac%20OS%20X%20Developer%20Preview

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9038169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档