正在寻找一个令人惊讶的并发Java程序

正在寻找一个令人惊讶的并发Java程序,java,multithreading,concurrency,Java,Multithreading,Concurrency,由于我正在编写一个着重于并发方面的剖析器,我正在寻找一个使用Java中同步机制的好的人工示例。我的分析器使一些与线程相关的操作可见;例如: 呼叫通知/等待 线程更改其状态 一个线程与另一个线程争夺监视器锁 一个线程在与另一个线程争用监视器锁后获取了它 测量每个方法的执行时间 哪个线程访问了某个方法,访问频率如何 等等 因此,我要寻找的是一个Java程序,乍一看,它似乎是可以理解的,但当执行它时,您开始怀疑结果。我希望我的分析器能够检测到背景中发生了什么 为了澄清我自己,我给大家举了一个例子

由于我正在编写一个着重于并发方面的剖析器,我正在寻找一个使用Java中同步机制的好的人工示例。我的分析器使一些与线程相关的操作可见;例如:

  • 呼叫通知/等待
  • 线程更改其状态
  • 一个线程与另一个线程争夺监视器锁
  • 一个线程在与另一个线程争用监视器锁后获取了它
  • 测量每个方法的执行时间
  • 哪个线程访问了某个方法,访问频率如何
  • 等等
因此,我要寻找的是一个Java程序,乍一看,它似乎是可以理解的,但当执行它时,您开始怀疑结果。我希望我的分析器能够检测到背景中发生了什么


为了澄清我自己,我给大家举了一个例子,Brian Goetz的《Java并发实践》一书给出了“有毒”代码示例,这些示例用于学习

@NotThreadSafe
public class ListHelper<E> {
    public List<E> list =
        Collections.synchronizedList(new ArrayList<E>());
    ...
    public synchronized boolean putIfAbsent(E x) {
        boolean absent = !list.contains(x);
        if (absent)
            list.add(x);
        return absent;
    }
}
@NotThreadSafe
公共类ListHelper{
公开名单=
Collections.synchronizedList(新的ArrayList());
...
公共同步布尔putIfAbsent(E x){
布尔缺席=!list.contains(x);
如果(缺席)
增加(x);
缺席返回;
}
}
这是线程安全类的扩展,通过方法
putIfAbsent
。因为
list
是同步的,但是
putIfAbsent
使用另一个锁作为列表上定义的方法来保护状态

探查器可以显示使用过的监视器锁,让用户惊讶的是(或不是…),用户会看到有两个监视器锁而不是一个

我不太喜欢这个例子,但如果我已经有一大堆好例子的话,我不会问


我发现我的问题与此类似:和


但它们只指损坏的并发程序。我也在寻找线程安全的实现,但还不清楚它们是否是线程安全的。

也许是部署?两者都不是非常人工的,但我可以想象在调试其中一个时需要好的工具。

我会回到过去,比如七年或更长时间,找到一些java.util.concurrent之前的开源代码。几乎任何运行自己的并发性的东西都会有一些微妙的错误,因为并发性很难正确实现

看看,特别是那些属于多线程正确性类别(右表列)的

这些错误中的每一个都包含了关于为什么某个特定的习惯用法不好以及如何解决它的参考资料。

这个怎么样

class ObjectReference {

  private volatile Object obj = null;      

  public void set(Object obj) {
    if (obj == null) {
      throw new IllegalArgumentException();
    }
    this.obj = obj;
    synchronized (this) {
      notifyAll();
    }
  }

  /**
   * This method never returns null
   */
  public Object waitAndGet() {
    if (obj != null) {
      return obj;
    }
    synchronized (this) {
      wait();
      return obj;
    }
  }
}
实际上,您可以从
waitAndGet()获取
null
。请参阅-

是一个经典的并发示例。有一个可能的解决方案,可以在网上找到更多


正如在第一个链接中所描述的,这个例子说明了许多常见的并发问题。请让您的探查器显示它可以跟踪多少

我建议大家四处看看(或询问作者)IBM竞赛基准测试套件,因为它包含许多Java并发错误(不幸的是不是大型开源程序)。这个基准测试的好处是已经记录了bug(类型和位置)

如果你想找到更多的程序,我建议你看看软件测试/并发程序质量领域的一些研究论文。他们应该指出他们在研究中使用的样本程序

如果所有这些都失败了,您可以尝试在GitHub(或类似服务)上搜索包含必要并发机制(即同步)的存储库。通过这种方式,您可能会发现大量Java代码,唯一的问题是没有记录错误(除非您寻找提交修复)


我认为这三个建议将为您提供足够的程序来测试您的并发探查器。

请参阅,以获得一致的小型Java难题流,其中许多应该适合您的测试需要。

@sarnold,tomcat非常简单,但如果涉及并发性,它有相当多的数据竞争。然而,总的争论点很少。Eclipse也不是高度并发的,GUI不是并发类型的程序。@我不同意说GUI不是“并发的”。通常,事件处理是在一个线程上完成的,该线程永远不会阻塞。繁重的计算是在后台线程中完成的(在eclipse中,一个很好的例子是编译,但所有的处理都是在后台完成的,比如下载eclipse更新、验证文件、从VCS更新代码、控制正在运行的应用程序/测试)@Nicolas,这不是并发的,在没有任何同步/冲突点的情况下同时执行很少的任务是一种无趣的情况。如果使用非阻塞IO,下载甚至不需要单独的线程。这不是一个“令人惊讶的并发”程序的例子。GUI可能会进行大量的计算,但通常这个过程不会影响GUI,有一个进度条或通过简单的消息传递就没有什么特别的了。如果你仔细考虑eclipse(或任何中等复杂的UI)以及它的使用方式,这并不像看上去那么简单。首先,即使只有几十个并发线程,仍然有。使UI无响应或更糟地陷入死锁是一个真正的问题。事实上,如果你的软件有很多同步问题,这是一个设计问题。Web服务器无共享架构就是一个例子。许多(可能数百个)并发请求,但没有共享状态。Scala和Clojure正在使用不可变对象和actor或transactionnal内存。即使在JDK lvl中,Java5也提供了execu