技术开发 频道

Java中的模式--单态

  If this optimization takes place, you have the same out-of-order write problem we discussed earlier.

  如果这个优化发生,将再次发生上边提到的问题,取得没有实例化完成的数据。

  以下部分为了避免我翻译错误误导打家,保留原文

  Another idea is to use the keyword volatile for the variables inst and instance.
  According to the JLS (see Resources), variables declared volatile are supposed to be sequentially consistent, and therefore, not reordered.
  But two problems occur with trying to use volatile to fix the problem with double-checked locking:
  The problem here is not with sequential consistency.
  Code is being moved, not reordered.
  Many JVMs do not implement volatile correctly regarding sequential consistency anyway.
  The second point is worth expanding upon. Consider the code in Listing 9:

  Listing 9. Sequential consistency with volatile

  class test
  {
  
private volatile boolean stop = false;
  
private volatile int num = 0;
  
public void foo()
  {
  num
= 100; //This can happen second
  stop
= true; //This can happen first
  
//...
  }
  
public void bar()
  {
  
if (stop)
  num
+= num; //num can == 0!
  }
  
//...
  }

  According to the JLS, because stop and num are declared volatile,they should be sequentially consistent. This means that if stop is ever true,num must have been set to 100.
  However, because many JVMs do not implement the sequential consistency feature of volatile,you cannot count on this behavior.
  Therefore, if thread 1 called foo and thread 2 called bar concurrently,thread 1 might set stop to true before num is set to 100.
  This could lead thread 2 to see stop as true, but num still set to 0.
  There are additional problems with volatile and the atomicity of 64-bit variables,but this is beyond the scope of this article.
  See Resources for more information on this topic.

  简单的理解上边这段话,使用volatile有可能能解决问题,volatile被定义用来保正一致性,但是很多虚拟机并没有很好的实现volatile,所以使用它也会存在问题。

  最终的解决方案:

  (1),单态模式2,使用同步方法。

  (2),放弃同步,使用一个静态变量,如下:

  class Singleton
  {
  
private Vector v;
  
private boolean inUse;
  
private static Singleton instance = new Singleton();
  
private Singleton()
  {
  v
= new Vector();
  inUse
= true;
  
//...
  }
  
public static Singleton getInstance()
  {
  
return instance;
  }
  }

   但使用静态变量也会存在问题,问题见这篇文章,而且如在文章开头提到的,使用EJB跨服务器,跨JVM的情况下,单态更是问题。好了是不是感觉单态模式根本没法使用了,其实上边都是特殊情况,这中特殊情况的出现是有条件的,只要根据你的具体应用,回避一些,就能解决问题,所以单态还是可以使用的。但是在使用前慎重,自己考虑好自己的情况适合哪种情况。

0
相关文章