Java同步机制

 1、Pattern源代码

(1)matcher()函数的作用是编译已有的正则表达式,然后返回对应序列的匹配器,其涉及到的同步机制:volatile和synchronized的使用,单例模式常用到的DCL的问题,互斥和可见性。这篇博客解释得很好:http://www.ibm.com/developerworks/cn/java/j-jtp06197.html,原理性强点的http://www.infoq.com/cn/articles/ftf-java-volatile,下面简要概括下。

  
  
  
  
  1. private transient volatile boolean compiled = false//定义为volatile后,一个线程执行完compile后,compiled立即被置为true,其他线程就可直接返回不用等待 
  2. public Matcher matcher(CharSequence input) { 
  3.  if (!compiled) { 
  4.      synchronized(this) { 
  5.   if (!compiled) 
  6.       compile(); 
  7.      } 
  8.  } 
  9.         Matcher m = new Matcher(this, input); 
  10.         return m; 
  11.     } 

(2)多线程最核心的问题就是同步,对于共享变量的访问的一致性。对于公司业务,web本身就是多线程,我们在写自己代码的时候尽量避免共享变量,防止同步问题的出现。但是必须要做的时候,还是要谨慎对待。锁,关键字synchronized是大家最熟悉的,提供两种特性:互斥和可见性,互斥就是一次只允许一个线程持有某个锁(锁就不普及了,对象锁、类锁等);可见性就是一个线程在锁释放之前保证对共享变量的修改对于下一个获得锁的线程是可见的。volatile可以保证变量具有可见性,但是不具有互斥性,保证共享变量的值对于多个线程是可见的,也就是共享变量值的变化每个线程都可以立即得知。原理是,多线程,每个线程都会有一个运行时都会将内存中的变量加载入内部缓存(L1、L2等),修改操作针对缓存中的数据,但是什么时候同步到内存就不一定了,其实也可以理解为工作内存和主内存,主内存是线程共享的,工作内存是线程独享的,分为缓存和堆栈,缓存保存主内存的拷贝,堆栈保存函数执行的局部变量,线程之间通过主内存完成共享变量的交互,这就产生了多个线程的同步问题,但是volatile保证变量的修改立即同步到系统内存,其他线程在从内存中读值的时候就是最新的了。总结为一句话:volatile修饰的共享变量可以同时被多个线程访问,每个线程访问的都是这个变量的最新值。

(3)volatile的使用很复杂,有两个前提:

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

理解起来比较复杂,但是有5个常用的场景可以很好的发挥volatile的作用,大家熟记就可以了,详细介绍可以看上面的IBM的博客。

#1 状态标志

共享变量只是标识一个事情是否完成,boolean型,只有true和false。上面举到的mathcer()函数就是这种情景,定义compiled为标志位,标识pattern是否编译过,如果编译通过直接用来构造matcher返回。只要一个线程运行完compile()就会设置compiled为true,其他线程会立即得知,就可以获知。如果不设置,那么当一个线程运行晚complie()后,工作内存中compiled置为true,但是主内存中还没设置为true,线程2就会继续执行到同步代码进行等待。

#一次安全发布

也就是说volatile修饰的变量属于引用,且一次初始化后,不会再改变,这种应用场景最特殊的就是解决单例模式DCL(双重检查锁定)方法遇到的问题。一旦实例化,不会改变,以后就直接返回。

  
  
  
  
  1. public class BaseTest { 
  2.   
  3.  private volatile static BaseTest test;//如果此处不是volatile,那么new BaseTest()乱序执行,当test不为null时,但是还没进行初始化,另一个线程判断test!=null,直接返回test,一个没有实例化的引用就会出错 
  4.  public BaseTest getInstance() 
  5.  { 
  6.   if(test==null
  7.   { 
  8.    synchronized (BaseTest.class) { 
  9.     if(test==null
  10.      test=new BaseTest(); 
  11.    } 
  12.   } 
  13.   return test; 
  14.  } 

#独立观察

比较好理解,也就是这个变量会一直更新,每个线程都想获得最新的变量值,但是不会改变。例如一个记录当前温度的变量,线程通过它获取最新的温度。

后面还有两个模式,不实用且容易出错,感兴趣的可以去看下上面的博客链接。

你可能感兴趣的:(java,同步机制)