小编ast*_*icx的帖子

Java中的内存屏障行为

在阅读了更多的博客/文章等之后,我现在对内存屏障之前/之后的加载/存储行为感到困惑.

以下是Doug Lea在他关于JMM的一篇澄清文章中的两个引用,它们都非常简单:

  1. 线程A在写入易失性字段f时可见的任何内容在读取f时都会对线程B可见.
  2. 请注意,两个线程都必须访问相同的volatile变量才能正确设置before-before关系.情况并非如此,线程A在写入易失性字段f时可见的所有内容在读取易失性字段g后变为线程B可见.

但是当我查看另一篇关于内存障碍的博客时,我得到了这些:

  1. 商店屏障,x86上的"sfence"指令强制屏障之前的所有存储指令发生在屏障之前,并将存储缓冲区刷新到缓存以供发布它的CPU.
  2. 负载屏障,在x86"lfence"指令,强制所有加载指令之后的阻隔后发生障碍,然后等待负载缓冲区对于CPU流失.

对我来说,Doug Lea的澄清比另一个更严格:基本上,这意味着如果负载屏障和存储屏障位于不同的监视器上,则无法保证数据的一致性.但后者意味着即使屏障位于不同的监视器上,数据的一致性也会得到保证.我不确定我是否正确理解这两个,而且我不确定它们中的哪一个是正确的.

考虑以下代码:

  public class MemoryBarrier {
    volatile int i = 1, j = 2;
    int x;

    public void write() {
      x = 14; //W01
      i = 3;  //W02
    }

    public void read1() {
      if (i == 3) {  //R11
        if (x == 14) //R12
          System.out.println("Foo");
        else
          System.out.println("Bar");
      }
    }

    public void read2() {
      if (j == 2) {  //R21
        if (x == 14) //R22
          System.out.println("Foo");
        else
          System.out.println("Bar"); …
Run Code Online (Sandbox Code Playgroud)

java multithreading java-memory-model memory-barriers

32
推荐指数
1
解决办法
5868
查看次数

RabbitMQ在"确认"模式下的通道行为

我在理解RabbitMQ的确认方面遇到了一些麻烦,我从RabbitMQ看到以下解释:

笔记

如果代理在将所述消息写入磁盘之前崩溃,则代理会丢失持久消息.在某些情况下,这会导致经纪人以令人惊讶的方式行事.例如,考虑这种情况:

  • 客户端将持久性消息发布到持久队列

  • 客户端使用队列中的消息(注意消息是持久的,队列是持久的),但还没有消息,

  • 经纪人去世并重新启动,并且

  • 客户端重新连接并开始使用消息.

此时,客户端可以合理地假设该消息将再次传递.情况并非如此:重启导致代理丢失消息.为了保证持久性,客户应该使用确认.如果发布者的频道处于确认模式,则发布者不会收到丢失消息的确认消息(因为消费者没有得到它并且没有写入磁盘).

然后我使用这个http://hg.rabbitmq.com/rabbitmq-java-client/file/default/test/src/com/rabbitmq/examples/ConfirmDontLoseMessages.java做一些基本测试并验证确认,但得到一些奇怪的结果:

  1. waitForConfirmsOrDie方法不会阻止生产者,这与我的期望不同,我想waitForConfirmsOrDie将阻止生成器,直到所有消息都被激活或其中一个消息被nack'd.
  2. 我从发布者中删除了channel.confirmSelect()和channel.waitForConfirmsOrDie(),并将使用者从auto ack更改为手动ack,我将所有消息发布到队列并逐个使用消息,然后我在停止期间停止rabbitmq服务器消费过程,我现在期望的是,在重启Rabbitmq服务器后,左侧消息将丢失,因为该通道未处于确认模式,但在服务器重启后仍然可以看到队列中的所有其他消息.

由于我是RabbitMQ的新手,任何人都可以告诉我,我对确认理解的问题在哪里?

rabbitmq

9
推荐指数
1
解决办法
7846
查看次数

IOException:网络适配器无法建立连接

我们不时在我们的生产环境中开始有这个"网络适配器无法建立连接"的问题,我做了很多谷歌并在这里经历了一些问题,但仍然没有得到解决方案.

以下是有关我们环境的一些信息:

  1. 我们正在使用RAC和2个oracle实例(版本10.2.0.4).
  2. 我们在RAC上运行了几个应用服务器(JBoss AS5).
  3. oracle-ds.xml中的连接url是"jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = db1_vip)(PORT = 1521))(ADDRESS =(PROTOCOL = TCP) )(HOST = db2_vip)(PORT = 1521))(LOAD_BALANCE = yes))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = G1db)(FAILOVER_MODE =(TYPE = SELECT)(METHOD = BASIC)(RETRIES = 120)( DELAY = 5))))"
  4. 我们将db1_vip/db2_vip以及2个oracle实例的实际ip添加到两个应用服务器的/ etc/hosts中
  5. oracle实例和应用服务器之间有防火墙,但是我们在两个oracle实例上都打开了1521端口.

我们运行以下测试来检查网络或oracle TNS监听器是否有任何问题:

  1. 从应用程序服务器运行ping到两个oracle实例,一切正常,没有任何数据包丢失.
  2. telnet 1521端口从应用服务器到两个oracle实例,没有错.
  3. tnsping也很好用.
  4. 我们检查了听众日志,但没有发现任何有价值

最奇怪的是,这个错误在一台应用服务器上每小时发生10次左右,但在另一台应用服务器上每天只发生1到2次.

任何人都可以对这个错误有所了解吗?

谢谢

[编辑方面4]:我们在找到一个oracle实例时发现超时问题,所以我们更改了jdbc url只连接一个实例,发现IOException再也没发生过,所以我们认为问题与数据库有关,DBA团队将继续研究这个.

[编辑方面3]:我们做了以下尝试:

  1. 禁用应用服务器和数据库服务器之间的防火墙
  2. 使用ip而不是主机名
  3. 使用wireshark检查是否存在任何tcp数据包问题.

他们都没有成功,有人请帮助〜

[编辑]:错误堆栈跟踪:

java.sql.SQLException: Io Exception: The Network Adapter could not establish the connection
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387) …
Run Code Online (Sandbox Code Playgroud)

java oracle jdbc

6
推荐指数
1
解决办法
5万
查看次数