如果一个static方法被标注为synchronized,是否意味者它在同一时间不能被两个不同线程的调用?即使这个类被实例化多次?举例说类A:
Class A {
  public A() {}
  public synchronized static method() {
  }
}那么是否以下的各种调用都不会同时出现,而是排队等候前面的执行结束?A.method();
A object1 = new A();
object1.method();
A object2 = new A();
object2.method();多谢!

解决方案 »

  1.   

    在Java中,使用synchronized关键字来进行线程的同步 
     
    一个设置了synchronized关键字的方法自动成为同步方法 
    进入方法则相当于以当前对象为信号量,上锁。退出时解锁。 
     
    Java还提供了wait()和notify(),notifyAll()方法辅助进行同步 
    wait()会解锁当前的信号量,使线程进入堵塞状态。直到使用 
    同一信号量的notify()或notifyAll()来唤醒它。 线程在不同时刻有不同的状态,正在被执行时,即占有CPU时 
    我们称之为Running状态。那么其它的状态线程自然是不能运行啦。 
    很可能有多个线程都不能运行吧,但它们不能运行的原因却是各不相同的。 
    那么由于相同原因不能运行的线程就会存在一个“池pool”中。 
    由于虚拟机线程调度而不运行的,处于 Runnable池中,表示万事俱备, 
    只差CPU,由于使用synchronized而阻塞的线程就会在对象锁 
    (object's lock pool)池中等待。而同步的方法中调用wait()后,线程则会 
    在wait池中等待。这里要注意了,首先wait()方法能得到执行说明当前线程 
    正在运行(在Running状态),从而说明它肯定拥有对象锁;第二,调用 
    wait()方法进入阻塞状态时,当前线程将释放对象锁(!!)第三, 
    在notify()或notifyAll()方法唤醒此线程时,它将进入 object's lock pool 
     池中等待,以重新获得对象锁。状态图如下所示。 
                         Schedule 
      (Runnable)     <------------->  (Running) 
            ^                          |    \ 
            |                          |     --\ 
            |                synchronized     wait() --must hav lock 
        acquire lock                   |         \ release lock 
            |                          |          \ 
            |                          |           \     
            |          (Blocked in)    |        (Bolcked in ) 
             ----------( object's )<----        ( object's  ) 
                       ( lock pool) <---------- ( wait pool ) 
                                      notify() 
      

  2.   

    对一种特殊的资源——对象中的内存——Java提供了内建的机制来防止它们的冲突。由于我们通常将数据元素设为从属于private(私有)类,然后只通过方法访问那些内存,所以只需将一个特定的方法设为synchronized(同步的),便可有效地防止冲突。在任何时刻,只可有一个线程调用特定对象的一个synchronized方法(尽管那个线程可以调用多个对象的同步方法)。下面列出简单的synchronized方法:
    synchronized void f() { /* ... */ }
    synchronized void g() { /* ... */ }
    每个对象都包含了一把锁(也叫作“监视器”),它自动成为对象的一部分(不必为此写任何特殊的代码)。调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized方法,除非第一个方法完成了自己的工作,并解除锁定。在上面的例子中,如果为一个对象调用f(),便不能再为同样的对象调用g(),除非f()完成并解除锁定。因此,一个特定对象的所有synchronized方法都共享着一把锁,而且这把锁能防止多个方法对通用内存同时进行写操作(比如同时有多个线程)。
    每个类也有自己的一把锁(作为类的Class对象的一部分),所以synchronized static方法可在一个类的范围内被相互间锁定起来,防止与static数据的接触。
      

  3.   

    另外我看了baitianhai(hong) 的文章后又多了一个问题:
    对于:
    Class A {
      public A() {}
      public synchronized static method1() {}
      public synchronized static method2() {}
    }
    是否A.method1()和A.method2()都是不能同时被同时调用的?(会遵循请求的先后顺序,依次执行?)
      

  4.   

    你的答案是该是对的,那个文章好想是这个意思,那是 think in java 里的
      

  5.   

    不能同时调用,synchronized关键字在你上面的例子里,锁定了载入的A的类,当一个方法结束后,线程监视器通知这个对象,让后其他的方法被监视器调用
      

  6.   

    我自己试过,在java1.4里不论你在什么地方加sync都可以保证不会把整个class锁住。如果你的class中有两个sync方法,这两个方法可以被同时调用,但每个sync方法不会被多个线程同时调用。给分吧! :)
      

  7.   

    错,类的锁定是局限在载入的某个jvm里面的.
      

  8.   

    to  hellking(杀他个干干净净) :
     我觉得不太对的,比如我现在想对static数据锁定,那你不是等于说 这样不可能实现了吗?
      

  9.   

    这个东西对我很重要,我希望得到确切的答复。在Java 1.3里面(应该和1.4一样的),sync的静态方法,static调用和实例化的Object调用都可以保证:某一时刻,该类的所有sync静态方法只有一个在运行?谢谢!
      

  10.   

    另外hellking(杀他个干干净净)说的我不是很明白:“两个方法可以被同时调用,但每个sync方法不会被多个线程同时调用”听起来像是自相矛盾?
      

  11.   

    也就是说,以下的问题答案是“是”!?在Java 1.3里面(应该和1.4一样的),sync的静态方法,static调用和实例化的Object调用都可以保证:某一时刻,该类的所有sync静态方法只有一个在运行?
      

  12.   

    to  leonzhao(灯泡):
    Class A {
      public A() {}
      public synchronized static method1() {}
      public synchronized static method2() {}
    }
    class m1 extends thread{
       while(true){
           A.method1();
       }
    }
    class m2 extends thread{
       while(true){
           A.method2();
       }
    }main(){
       m1.start();
       m2.start();
    }class A 的两个方法可以同时被调用,如果thread m2也调用a.method1()的话,将按调用顺序执行,可以肯定m1和m2中有一个不会执行了。
    回:某一时刻,该类的所有sync静态方法只有一个在运行?
    在某一时刻,该类的所有sync静态方法都可以被执行,但每个sync方法只有一个thread在执行(调用)它。
      

  13.   

    你可以亲自试一下,我以前也听说过如果某个sync方法被调用那个他所在的class也被锁上了,该class的其他sync方法将不可以同时被调用。
    我在java1.4上试的结果证实这个说法是错误的!
    try it yourself!!
      

  14.   

    补充一下:
    Class A {
      public A() {}
      public synchronized static method1() { do a dead circle }
      public synchronized static method2() { do a dead circle }
    }
      

  15.   

    to hellking(杀他个干干净净) 我做了实验,但是和你的结果不一样啊,测试代码如下:public class StaticClass { public StaticClass() {
    } public static synchronized void method1() {
    System.out.println("Start method 1");
    while(true);
    } public static synchronized void method2() {
    System.out.println("Start method 2");
    while(true);
    }
    }public class Thread1 extends Thread { public Thread1() {
    } public void run() {
    //StaticClass.method1();
    StaticClass sc = new StaticClass();
    sc.method1();
    }
    }public class Thread2 extends Thread { public Thread2() {
    } public void run() {
    //StaticClass.method2();
    StaticClass sc = new StaticClass();
    sc.method2();
    }
    }public class ThreadRunTester {
    public static void main(String[] args) {
    Thread1 t1 = new Thread1();
    Thread2 t2 = new Thread2();
    t1.start();
    t2.start();
    }
    }结果只打出一行信息,不知道你的测试代码是什么样的。另外我测试了1.3和1.4,结果是一致的。
      

  16.   

    改一下你的方法:
    public static synchronized void method1() {
       while(true){
          System.out.print("A");
          Thread.currentThread.sleep(100);
       }
    }
    public static synchronized void method2() {
       while(true){
          System.out.print("B");
          Thread.currentThread.sleep(100);
       }
    }结果是A和B交替出现!
      

  17.   

    不要在jbuilder7里跑,结果是错误的!
      

  18.   

    import java.net.*;
    import java.io.*;public class SyncTest extends Thread
    {
    int whichfunc=0;
    public static void main(String [] args)throws Exception
    {
    SyncTest syn1=new SyncTest(1);
    SyncTest syn2=new SyncTest(2);
    syn1.join();
    syn2.join();
    }
    public SyncTest(int which)
    {
    whichfunc=which;
    start();
    }
            public void run() 
            {
             try{
             if(whichfunc==1){
             func1();
             }
             else if(whichfunc==2)
             {
             func2();
             }
             }
             catch(Exception e)
             {
             e.printStackTrace();
             }
            }
             private static int order=0;
    private  synchronized static void func1()throws Exception
    {
    System.out.println("this is func1,value is "+order++);
    Thread.sleep(2000);
    System.out.println("end of func1,value is "+order);

            }
            private  synchronized static void func2()throws Exception
            {
             System.out.println("this is func2,value is "+order++);
    Thread.sleep(2000);
    System.out.println("end of func2,value is "+order);
            }
    }
    对比func1和func2
    如果两着都是synchronized static 则两者被同步
      
    如果两者都只是static  而不是synchronized,则不能被同步如果两者都只是synchronized而不是static 也不能被同步,因为他们不是同一对象的方法。如果两者都是synchronized,但是有一个不是static 而另一个是,
    也不能被同步所以我认为synchronized作用在static方法前的时候,是对特定的Class对象在全局中同步。
    synchronized作用在非static方法前的时候,是对特定的对象同步。
    http://www.javaworld.com/javaworld/jw-04-1999/jw-04-toolbox.html
      

  19.   

    但是非静态变量也可以模拟static方法的同步
    例如对于上面两个例子中func1改为
    private  void func1()throws Exception
    {

    synchronized(this.getClass()) 
    {
    System.out.println("this is func1,value is "+order++);
    Thread.sleep(2000);
    System.out.println("end of func1,value is "+order);
    }

            }
    效果是一样的。
      

  20.   

    to hhv():
    sync和static方法并没有任何联系,把sync和static分开看作两个特性来看就简单多了。被sync的方法和块在某一时刻只有一个thread在调用他。static的变量和方法和类在整个jvm中只有一个。
      

  21.   

    to hellking(杀他个干干净净) :
    非static 方法是必须有所依托的对象的,而static方法在语义上是不需要有一个对象。synchronized 有作用域的问题,不是对整个JVM都有效,这一点必须明白。
    synchronized 实际上是对一个锁的加琐和释放的问题。对非static方法,synchronized的作用隅只是所依托的对象而不是全局唯一的,而 static 方法synchronized作用域是类的Class对象,由于这个对象是全局唯一的,所以static 方法是一个时候只能有一个访问他。在这种意义上我猛也可以把static 方法看看成是非static的方法,只不过是一个Class对象的方法。
    因此sync同static 是有关系的。
    被sync的方法和块在某一时刻只有一个thread在调用他???
    当两个对象实例线程调用一个sync的非static方法时候,sync不起任何作用,这是经过理论和实践检验的。
      

  22.   

    为什么下面这个代码并没有锁住线程对象c?
    class ThreadA {
    /**
    * @param args
    */
    /**
    * @param args
    */
    public static void main(String[] args) {
    Thread b = new Thread(new ThreadA());
    //ThreadA b = new ThreadA();
    b.start();
    Object obj = new Object();
    System.out.println("b is start...."); Thread c = new Thread();
    c.start();
    synchronized (c)// 括号里的b是什么意思,起什么作用?
    {
    try {
    //Thread.sleep(20);
    //b.setTotal();
    System.out.println("Waiting for b to complete...");
    c.wait();// 这一句是什么意思,究竟让谁wait?
    System.out.println("Completed.Now back to main thread");
    } catch (InterruptedException e) {
    }
    }
    }
    }
    public class ThreadA implements Runnable {
    public int total;


    public void setTotal(){
    total++;
    }

    public void run(){
    synchronized (this) {

    System.out.println("ThreadA is running..");
    /*try{
    Thread.sleep(1000);
    }catch(InterruptedException e){}*/
    for (int i = 0; i < 20; i++) {
    total += i;
    System.out.println("total is " + total);
    }
    notify();
    }
    }}