与网友讨论之初识同步

    技术2022-05-11  72

        题记        使用Java也有些时间了,头脑里总会闪现出一些似是而非的问题。于是,我考虑建立一个专题,专门来讨论这些问题,初步把它定位在FAQ的形式上。这是第一篇,初步讨论关于同步的问题。        为什么需要同步?    以下是一简单计数器的例子:<%@ page contentType="text/html;charset=GB2312" %><%@ page import="java.io.*" %><html><body>    <%!      public int number;      private String countFile;     public int number(){         try{             ServletContext application=getServletContext();             countFile=application.getRealPath("/");                    BufferedReader file=new BufferedReader(new FileReader(countFile+"hits.txt"));             number=java.lang.Integer.parseInt(file.readLine());             number++;         }         catch(Exception e){             System.out.println(e);         }         return number;     }     public synchronized void counter(){         number();         try{             File f=new File(countFile+"hits.txt");             PrintWriter pw=new PrintWriter(new FileWriter(f));             pw.print(number);             pw.close();        }        catch(Exception e){            System.out.println(e);        }                  }  %>  <%  if(session.isNew()){          counter();       }  out.println(number); %></body></html>    关键词synchronized定义了同步的概念,它可以作为方法修饰符,亦可作为方法内语句。在多线程条件下它限制了对共享资源的访问。方法counter()锁存地获取和释放IO资源,即持有该对象的lock。这种机制可以避免一个线程在进行文件读写操作时,其他线程如果也操作该资源,会抛出异常的情况。        什么时候需要同步机制?    第一,如果对象的更新影响到只读方法,那么只读方法也应被定义为同步的,例如上面的IO操作。第二,如果两个或两个以上的线程都修改一个对象,那么把执行修改的方法定义为同步的。

        减少同步    增加无谓的同步控制,几乎和遗漏必要的同步一样糟糕。据文献记载,没有使用同步机制的操作几乎要比使用这一机制的快数倍!原因在于锁存地获取和释放资源,不再通过monitorenter和monitorexit操作码来进行,而是会检查ACC_SYNCHRONIZED属性标记,这一操作是要花费相当的代价。并且,过渡的同步控制可能导致代码死锁,并发度降低。所以应该避免无谓的同步。        注意问题    synchronized关键词一般用于虚拟锁,锁住的不是方法或代码,而是调用这个方法的对象。例如,对于一个构造函数Test(int n),由于变量n的不同,可以构造出不同的Test对象a和b,如果a、b同时访问同步区域,结果只会使synchronized形同虚设!    a和b如果要同时访问同步方法,只有该同步方法为static时才能达到同步的目的,否则,a调用a的方法,b调用b的方法,即使方法声明为同步的,但在不同对象域中它们根本达不到同步的目的。(请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处:http://blog.csdn.net/rosen


    最新回复(0)