繁体   English   中英

基于条件的Java并发

[英]Java Concurrency based on condition

创建一个接受整数作为参数的方法并在控制台上打印。 该方法由多个线程访问。 如果两个或多个线程使用相同的值调用该方法,则仅一个线程应允许打印该值,其他线程应等待。 如果值不同,则所有线程都应允许打印该值。 我知道interning在这里会有所帮助,但是Java进行intern直到值小于128。之后,两个具有相同值的Integer是不同的对象...可以这样做吗? 有条件同步的任何规定吗?

关于防止多个线程打印相同值,但允许它们打印不同线程的要求

防止这种情况的最简单方法是已经打印了一组整数。 由于要打印,使用锁的开销很小。

 Set<Integer> printed = Collections.synchronizedSet(new HashSet<Integer>());

 // when printing
 if (printed.add(num)) // will one be true the first time for each number
     System.out.println("num: " + num);

能做到吗

打印到控制台已经同步,无论您做什么,所有线程都将同步其打印,无论您做什么。 添加更多锁定不会改变这一点。

例如从实现System.out和err的PrintStream中

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

您不能简单地决定忽略来自调用方的synchronized

有条件同步的任何规定吗?

最简单的操作是锁定不同的锁或本地线程。 锁定不满意的对象非常快。

例如

synchronized(shared ? sharedObject : Thread.currentThread()) {

}

顺便说一句,这是一件非常奇怪/令人困惑的事情。 我会认真考虑更改您的设计,因此这不是必需的。 编写普通的多线程代码很难编写/理解。

private static final Set<Integer> lockedIntegers = new HashSet<>();

private void lock(Integer key) throws InterruptedException {
    synchronized (lockedIntegers) {
        while (!lockedIntegers.add(key)) {
            lockedIntegers.wait();
        }
    }
}

private void unlock(Integer key) {
    synchronized (lockedIntegers) {
        lockedIntegers.remove(key);
        lockedIntegers.notifyAll();
    }
}

public void printEqualIntegersSynchronously(Integer key) throws InterruptedException {
    try {
        lock(key);

        System.out.println(key);
        //Do whatever you need with your key.
        //For different keys this part is executed in parallel.
        //For equal keys this part is executed synchronously.

    } finally {
        unlock(key);
    }
}

最后尝试 -非常重要-即使操作引发异常,您也必须保证在操作后解锁等待线程。 'System.out.println'很可能永远不会抛出异常-但是在其他实际情况下,“最终尝试”是强制性的。 顺便说一下,“ System.out.println”已经被自己同步了,所以对于“ System.out.println”来说就不需要了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM