【问题标题】:ImageIO is synchronizedImageIO 已同步
【发布时间】:2013-08-07 21:57:27
【问题描述】:

我有一个用户上传图片的网络应用程序。我们通过 ImageIO.read() 验证图像数据,并对生成的 BufferedImage 执行一些简单的转换,然后将其保存到磁盘。

在执行负载测试时,我们意识到当许多请求同时进入时,它们会在 ImageIO.read() 调用中被阻塞。深入挖掘,我们注意到 JPEGImageReader 是同步的,并且一次只创建一个 BufferedImage。

还有其他人遇到过这个吗?我已经在谷歌上搜索了几天,还没有遇到另一个遇到这个问题的人,所以也许我做错了什么。我想不出任何合乎逻辑的理由。这似乎与无法针对某些内存泄漏问题为每个图像创建单独的读取器和写入器有关,但这种解释对我来说似乎相当薄。

编辑:Here 是一种性能工具,可以分解需要这么长时间的东西。我相信这是由于所有线程都在等待同步锁,JPEGImageReader source。

编辑:JAI 库本来可以工作,只是 OpenJDK 删除了对它的关键部分的支持,明确地是 JPEG 编解码器。

解决方案:考虑到我花费大量时间尝试寻找替代解决方案但未能做到,我最好的解决方案是针对请求异步处理图像。因此,当请求进来时,原始图像数据被存储为假定有效的图像;然后,请求线程之外的异步进程将一次处理每个图像。 由于 ImageIO 库的同步性,尝试一次处理多个图像没有任何好处。 图像可以并行处理,因为该库不是同步的,只是效率低下。

虽然异步处理会增加一定程度的复杂性,但就修改图像而言,这可能是一个好主意。行不通的是我们无法在每个请求中处理原始图像,这意味着我们的系统必须假设每个图像都是有效的图像数据。当异步处理器确实开始处理图像时,如果数据不好,系统可能会出现不一致。

【问题讨论】:

  • 你在运行多个线程吗?你是说多个JPEGImageReader 实例在类上序列化(即单线程)?您如何确定是这种情况?如果是这样,他们都锁定/等待的监视器在哪里?
  • 这绝对是多线程的,因为它们是 Tomcat 中的单独请求。我开始相信 ImageIO 只是在底层创建了一个底层 JPEGImageReader。请参阅:JPEGImageReader。我们 99% 确信这是正在发生的事情,因为当我们注释掉创建 BufferedImage 并进行转换并将 InputStream 内容保存到磁盘的部分时,实际上是在对 CPU 征税。否则,它们在负载时的使用率约为 5%。
  • 听起来你需要在ImageIO中下一层并使用创建阅读器的方法,而不是方便的方法。
  • 直接使用读取器/写入器的问题是我实际上需要一些来自 ImageIO 的便利实用程序。我希望能够向它抛出一个输入流并取回一个“已验证”的图像。如果我走低,我要么被锁定在一种格式中,例如JPEG,否则我最终会重写库的很大一部分。
  • 从您的分析数据(可能不完整)来看,问题似乎是 OpenJDK 颜色管理 (LCMS) 中的严重性能问题。我认为这个 CMS 不用于 Sun/Oracle VM。您是否尝试过其他虚拟机? JPEGImageReader 在内部使用每个实例的同步这一事实不应导致您得出 ImageIO 无法同时处理多个图像的结论。我很确定它可以。

标签: java synchronization javax.imageio


【解决方案1】:

编辑:首先,haraldK 的答案是正确的,而我原来的答案是错误的。但是它不能被删除,只有编辑过的 OP 才能重新分配勾号。

ThreadLock 机制的作用是阻止线程访问来自它们自己的不同读取器,而不是阻止线程独立于其他线程并与其他线程同时访问自己的读取器。

因此 ImageIO 的 JPEGImageReader 应该可以异步工作。

【讨论】:

  • ps 我知道这不是一个完整的“解决方案”,对此感到抱歉
  • 没关系。如果我让它工作,我会给你检查和解决复选标记,并用解决方案更新我的问题。谢谢!
  • 我将其标记为正确,因为据我所知,这是最优化的方法。问题出在 OpenJDK 上,它不再支持 JAI,但我发现的所有其他库都依赖于 ImageIO。
  • @pstanton 如果您仔细查看您发布的源代码,您会发现如果在多个线程中使用该方法不会阻塞。它抛出一个IllegalStateException。 PS:我确实认为您在帮助 OP 找到解决方法方面所做的努力值得称赞,请不要误会我的意思。只是我认为结论是错误的,并试图避免混淆。 :-)
【解决方案2】:

在执行负载测试时,我们意识到当许多请求同时进入时,它们会在 ImageIO.read() 调用中被阻塞。深入挖掘,我们注意到 JPEGImageReader 是同步的,并且一次只创建一个 BufferedImage。

还有其他人遇到过这个吗?

正如我在评论部分提到的:从性能分析来看,这似乎是OpenJDK(lcms)的颜色管理系统的性能问题,因为颜色转换应该不会花这么长时间。我无法进一步调试的猜测是,即使 ImageIO 能够并行解码,这个问题也会使解码(看起来)同步。

这是一个 SSCCE,它显示 ImageIO 完全能够同时解码多个图像。

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

class MultipleJPEGDecoding {
    private static int threads = Runtime.getRuntime().availableProcessors();
    private static ExecutorService executorService = Executors.newFixedThreadPool(threads * 4);

    public static void main(final String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            final int index = i;

            executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ImageInputStream stream = ImageIO.createImageInputStream(new File(args[index % args.length]));
                        try {
                            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
                            if (!readers.hasNext()) {
                                System.err.println("No reader!");
                                return;
                            }

                            ImageReader reader = readers.next();
                            reader.setInput(stream);
                            reader.addIIOReadProgressListener(new ProgressListener(index));

                            try {
                                reader.read(0);
                            }
                            finally {
                                reader.dispose();
                            }
                        }
                        finally {
                            stream.close();
                        }
                    }
                    catch (Exception e) {
                        System.err.printf("Error reading %d\n", index);
                        e.printStackTrace();
                    }
                }
            });
        }

        executorService.shutdown();
    }

    static class ProgressListener implements IIOReadProgressListener {
        final static AtomicInteger simultaneous = new AtomicInteger(0);

        final int index;
        int nextProgress = 25;

        public ProgressListener(int index) {
            this.index = index;
        }

        public void imageStarted(ImageReader source, int imageIndex) {
            int inProgress = simultaneous.incrementAndGet();
            System.err.printf("Started reading image %d (now decoding %d images simultaneous)...\n", index, inProgress);
        }

        public void imageComplete(ImageReader source) {
            int inProgress = simultaneous.decrementAndGet();
            System.err.printf("Done reading image %d%s.\n", index, inProgress > 0 ? String.format(" (still decoding %d other images)", inProgress) : "");
        }

        public void imageProgress(ImageReader source, float percentageDone) {
            if (percentageDone > nextProgress) {
                int inProgress = simultaneous.get();
                System.err.printf("Progress on image %d (now decoding %d images simultaneous)...\n", index, inProgress);
                nextProgress += 25;
            }
        }

        public void sequenceStarted(ImageReader source, int minIndex) {
        }

        public void sequenceComplete(ImageReader source) {
        }

        public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
        }

        public void thumbnailProgress(ImageReader source, float percentageDone) {
        }

        public void thumbnailComplete(ImageReader source) {
        }

        public void readAborted(ImageReader source) {
        }
    }
}

输出如下:

Started reading image 5 (now decoding 2 images simultaneous)...
Started reading image 0 (now decoding 16 images simultaneous)...
Started reading image 14 (now decoding 15 images simultaneous)...
Started reading image 4 (now decoding 14 images simultaneous)...
Started reading image 13 (now decoding 1 images simultaneous)...
Started reading image 11 (now decoding 13 images simultaneous)...
Started reading image 2 (now decoding 12 images simultaneous)...
Started reading image 15 (now decoding 4 images simultaneous)...
Started reading image 8 (now decoding 11 images simultaneous)...
Started reading image 7 (now decoding 10 images simultaneous)...
Started reading image 9 (now decoding 9 images simultaneous)...
Started reading image 6 (now decoding 8 images simultaneous)...
Started reading image 10 (now decoding 7 images simultaneous)...
Started reading image 1 (now decoding 6 images simultaneous)...
Started reading image 3 (now decoding 5 images simultaneous)...
Started reading image 12 (now decoding 3 images simultaneous)...
Progress on image 11 (now decoding 16 images simultaneous)...
Progress on image 15 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 5 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Done reading image 3 (still decoding 15 other images).
Started reading image 16 (now decoding 15 images simultaneous)...
Progress on image 11 (now decoding 15 images simultaneous)...
Done reading image 13 (still decoding 14 other images).
Started reading image 17 (now decoding 15 images simultaneous)...
Progress on image 5 (now decoding 15 images simultaneous)...
Progress on image 4 (now decoding 15 images simultaneous)...
Progress on image 11 (now decoding 15 images simultaneous)...
Done reading image 9 (still decoding 14 other images).
Progress on image 5 (now decoding 15 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 11 (still decoding 14 other images).
Started reading image 19 (now decoding 15 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 5 (still decoding 14 other images).
Started reading image 18 (now decoding 15 images simultaneous)...
Progress on image 15 (now decoding 15 images simultaneous)...
Done reading image 1 (still decoding 14 other images).
Started reading image 21 (now decoding 15 images simultaneous)...
Progress on image 15 (now decoding 15 images simultaneous)...
Progress on image 21 (now decoding 15 images simultaneous)...
Done reading image 15 (still decoding 14 other images).
Progress on image 6 (now decoding 14 images simultaneous)...
Progress on image 21 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 21 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Done reading image 7 (still decoding 13 other images).
Started reading image 23 (now decoding 14 images simultaneous)...
Progress on image 10 (now decoding 14 images simultaneous)...
Progress on image 23 (now decoding 14 images simultaneous)...
Progress on image 14 (now decoding 14 images simultaneous)...
Started reading image 22 (now decoding 15 images simultaneous)...
Progress on image 0 (now decoding 15 images simultaneous)...
Done reading image 21 (still decoding 14 other images).
Started reading image 24 (now decoding 15 images simultaneous)...
Started reading image 20 (now decoding 16 images simultaneous)...
Progress on image 2 (now decoding 16 images simultaneous)...
Progress on image 8 (now decoding 16 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 17 (still decoding 14 other images).
Started reading image 25 (now decoding 15 images simultaneous)...
Progress on image 23 (now decoding 15 images simultaneous)...
Done reading image 19 (still decoding 15 other images).
Started reading image 26 (now decoding 16 images simultaneous)...
Progress on image 23 (now decoding 16 images simultaneous)...
Done reading image 23 (still decoding 15 other images).
Started reading image 27 (now decoding 16 images simultaneous)...
Progress on image 4 (now decoding 16 images simultaneous)...
Progress on image 27 (now decoding 16 images simultaneous)...
Progress on image 27 (now decoding 16 images simultaneous)...
Progress on image 6 (now decoding 16 images simultaneous)...
Progress on image 12 (now decoding 16 images simultaneous)...
Progress on image 20 (now decoding 16 images simultaneous)...
Progress on image 0 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 14 (now decoding 16 images simultaneous)...
Progress on image 10 (now decoding 16 images simultaneous)...
Progress on image 8 (now decoding 16 images simultaneous)...
Progress on image 18 (now decoding 16 images simultaneous)...
Done reading image 25 (still decoding 15 other images).

[...]

Progress on image 75 (now decoding 12 images simultaneous)...
Started reading image 73 (now decoding 13 images simultaneous)...
Progress on image 75 (now decoding 13 images simultaneous)...
Progress on image 73 (now decoding 13 images simultaneous)...
Progress on image 75 (now decoding 13 images simultaneous)...
Started reading image 74 (now decoding 14 images simultaneous)...
Progress on image 66 (now decoding 14 images simultaneous)...
Progress on image 64 (now decoding 14 images simultaneous)...
Progress on image 73 (now decoding 14 images simultaneous)...
Progress on image 60 (now decoding 14 images simultaneous)...
Progress on image 74 (now decoding 14 images simultaneous)...
Progress on image 58 (now decoding 14 images simultaneous)...
Done reading image 75 (still decoding 13 other images).
Progress on image 73 (now decoding 13 images simultaneous)...
Started reading image 77 (now decoding 14 images simultaneous)...
Done reading image 73 (still decoding 13 other images).
Progress on image 77 (now decoding 13 images simultaneous)...
Started reading image 78 (now decoding 14 images simultaneous)...
Progress on image 60 (now decoding 14 images simultaneous)...
Done reading image 48 (still decoding 13 other images).
Progress on image 77 (now decoding 13 images simultaneous)...
Started reading image 79 (now decoding 14 images simultaneous)...
Started reading image 70 (now decoding 15 images simultaneous)...
Progress on image 52 (now decoding 15 images simultaneous)...
Progress on image 71 (now decoding 15 images simultaneous)...
Started reading image 72 (now decoding 16 images simultaneous)...
Progress on image 71 (now decoding 16 images simultaneous)...
Progress on image 54 (now decoding 16 images simultaneous)...
Progress on image 68 (now decoding 16 images simultaneous)...
Progress on image 64 (now decoding 16 images simultaneous)...
Progress on image 66 (now decoding 16 images simultaneous)...
Progress on image 62 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 77 (now decoding 16 images simultaneous)...
Progress on image 68 (now decoding 16 images simultaneous)...
Done reading image 79 (still decoding 15 other images).
Done reading image 77 (still decoding 14 other images).
Started reading image 81 (now decoding 15 images simultaneous)...
Progress on image 74 (now decoding 15 images simultaneous)...
Progress on image 81 (now decoding 15 images simultaneous)...
Progress on image 81 (now decoding 15 images simultaneous)...
Progress on image 78 (now decoding 15 images simultaneous)...
Done reading image 60 (still decoding 14 other images).
Started reading image 82 (now decoding 15 images simultaneous)...
Started reading image 80 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 14 images simultaneous)...
Progress on image 66 (now decoding 14 images simultaneous)...
Progress on image 70 (now decoding 14 images simultaneous)...
Done reading image 52 (still decoding 14 other images).
Done reading image 71 (still decoding 15 other images).
Progress on image 81 (now decoding 16 images simultaneous)...
Started reading image 84 (now decoding 15 images simultaneous)...
Started reading image 83 (now decoding 16 images simultaneous)...
Progress on image 58 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Done reading image 81 (still decoding 15 other images).
Started reading image 85 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Progress on image 74 (now decoding 16 images simultaneous)...
Done reading image 66 (still decoding 15 other images).
Started reading image 86 (now decoding 16 images simultaneous)...
Progress on image 64 (now decoding 16 images simultaneous)...
Progress on image 70 (now decoding 16 images simultaneous)...
Progress on image 78 (now decoding 16 images simultaneous)...
Progress on image 54 (now decoding 16 images simultaneous)...
Done reading image 58 (still decoding 15 other images).
Started reading image 87 (now decoding 16 images simultaneous)...
Progress on image 87 (now decoding 16 images simultaneous)...
Progress on image 84 (now decoding 16 images simultaneous)...
Progress on image 87 (now decoding 16 images simultaneous)...
Done reading image 64 (still decoding 15 other images).
Started reading image 88 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 16 images simultaneous)...
Done reading image 83 (still decoding 15 other images).
Progress on image 62 (now decoding 15 images simultaneous)...
Progress on image 70 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Started reading image 89 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Progress on image 89 (now decoding 16 images simultaneous)...
Done reading image 85 (still decoding 15 other images).
Progress on image 89 (now decoding 15 images simultaneous)...
Progress on image 82 (now decoding 15 images simultaneous)...
Progress on image 80 (now decoding 15 images simultaneous)...
Done reading image 74 (still decoding 14 other images).
Started reading image 91 (now decoding 15 images simultaneous)...
Started reading image 90 (now decoding 16 images simultaneous)...
Done reading image 62 (still decoding 15 other images).
Progress on image 87 (now decoding 15 images simultaneous)...
Progress on image 68 (now decoding 15 images simultaneous)...
Done reading image 87 (still decoding 14 other images).
Progress on image 91 (now decoding 14 images simultaneous)...
Started reading image 93 (now decoding 15 images simultaneous)...
Progress on image 93 (now decoding 15 images simultaneous)...
Progress on image 91 (now decoding 15 images simultaneous)...
Progress on image 91 (now decoding 15 images simultaneous)...
Progress on image 80 (now decoding 15 images simultaneous)...
Started reading image 92 (now decoding 16 images simultaneous)...
Done reading image 91 (still decoding 15 other images).
Started reading image 94 (now decoding 16 images simultaneous)...
Progress on image 93 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Progress on image 93 (now decoding 16 images simultaneous)...
Done reading image 93 (still decoding 15 other images).
Started reading image 95 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Done reading image 95 (still decoding 15 other images).
Started reading image 96 (now decoding 16 images simultaneous)...
Progress on image 94 (now decoding 16 images simultaneous)...
Progress on image 89 (now decoding 15 images simultaneous)...
Done reading image 89 (still decoding 14 other images).
Done reading image 54 (still decoding 15 other images).
Started reading image 97 (now decoding 14 images simultaneous)...
Started reading image 98 (now decoding 15 images simultaneous)...
Done reading image 70 (still decoding 13 other images).
Started reading image 99 (now decoding 16 images simultaneous)...
Progress on image 82 (now decoding 16 images simultaneous)...
Progress on image 99 (now decoding 16 images simultaneous)...
Progress on image 99 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Done reading image 68 (still decoding 15 other images).
Done reading image 97 (still decoding 14 other images).
Progress on image 78 (now decoding 14 images simultaneous)...
Progress on image 99 (now decoding 14 images simultaneous)...
Done reading image 99 (still decoding 13 other images).
Progress on image 86 (now decoding 13 images simultaneous)...
Done reading image 72 (still decoding 12 other images).
Progress on image 82 (now decoding 12 images simultaneous)...
Progress on image 98 (now decoding 12 images simultaneous)...
Progress on image 84 (now decoding 12 images simultaneous)...
Progress on image 90 (now decoding 12 images simultaneous)...
Done reading image 76 (still decoding 11 other images).
Progress on image 92 (now decoding 11 images simultaneous)...
Progress on image 80 (now decoding 11 images simultaneous)...
Progress on image 94 (now decoding 11 images simultaneous)...
Progress on image 88 (now decoding 11 images simultaneous)...
Progress on image 84 (now decoding 11 images simultaneous)...
Progress on image 90 (now decoding 11 images simultaneous)...
Progress on image 92 (now decoding 11 images simultaneous)...
Progress on image 86 (now decoding 11 images simultaneous)...
Progress on image 94 (now decoding 10 images simultaneous)...
Done reading image 84 (still decoding 9 other images).
Progress on image 92 (now decoding 9 images simultaneous)...
Done reading image 78 (still decoding 10 other images).
Progress on image 88 (now decoding 9 images simultaneous)...
Progress on image 90 (now decoding 9 images simultaneous)...
Done reading image 80 (still decoding 8 other images).
Done reading image 82 (still decoding 7 other images).
Progress on image 86 (now decoding 7 images simultaneous)...
Progress on image 96 (now decoding 7 images simultaneous)...
Progress on image 88 (now decoding 7 images simultaneous)...
Done reading image 90 (still decoding 6 other images).
Done reading image 92 (still decoding 5 other images).
Progress on image 98 (now decoding 5 images simultaneous)...
Done reading image 94 (still decoding 4 other images).
Done reading image 86 (still decoding 3 other images).
Progress on image 96 (now decoding 3 images simultaneous)...
Done reading image 88 (still decoding 2 other images).
Progress on image 98 (now decoding 2 images simultaneous)...
Progress on image 96 (now decoding 2 images simultaneous)...
Done reading image 98 (still decoding 1 other images).
Done reading image 96.

【讨论】:

  • 这并不能证明什么。您所证明的只是您可以将请求排队到解码器。您还没有证明它们是同时解码的。该类的源代码清楚地表明这是不可能的。
  • @pstanton 源代码说 instance 是同步的(但 API 文档已经指定读者无论如何都不能被线程共享)。 ImageIO 将使用不同的实例进行多次调用,因此它会一次解码多个图像(如我的代码所示)。请求没有排队,它们同时被解码。我将更新代码以使其更清晰。
  • 我承认我没有对此进行测试,但是记录对代码的调用永远不会显示真正发生的事情。对此进行测试的唯一方法是对JPEGImageReader 的内部设置断点。我不想看起来像是在捍卫我的职位,我不是,我希望你是对的。将第一次点击断点到 JPEGImageReader.readInternal 并查看它是否停止所有其他“同时”读取...
  • @pstanton 我不明白你认为我的代码有什么问题?它现在同时报告多个图像的进度(我什至写了a version that shows the images while decoding,代码有点长,但如果你愿意,请测试它)。如果我创建一个断点,那不就是在该断点处暂停我的所有线程吗?这能证明什么?
  • 你是对的。 'threadLock' 是为了阻止不同的线程访问不同的读者,而不是阻止不同的线程拥有自己的读者。为混淆的事情道歉。将删除我的答案;)
猜你喜欢
  • 1970-01-01
  • 2015-02-28
  • 2017-01-26
  • 2017-10-20
  • 1970-01-01
  • 2013-02-12
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多