设一个类的A函数是synchronized的,在A内部弹出一消息框,使A的执行时间很长,此时发现在消息框未退出时,另一个synchronized函数B可被顺利进入(对同一个对象)。synchronized不起作用了?

解决方案 »

  1.   

    没有代码很难判断是哪里的问题
    我blog中有一个《Java线程之线程同步》,你可以参考下:
    http://blog.csdn.net/mq612/archive/2007/03/04/1520583.aspx
      

  2.   

    synchronized不太可能不起作用的,一定是你的程序设计欠妥
      

  3.   

    我写一个测试程序:import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    //import javax.swing.JOptionPane;public class TestSyn extends JFrame
    {
      private ActionListener alButton;
      private JButton jbB1,jbB2;
      private Timer mainTimer;
      public TestSyn()
      {
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("TestSyn");
        alButton=new ButtonListener(this);
        jbB1=new JButton("Button1");
        jbB1.addActionListener(alButton);
        jbB2=new JButton("Button2");
        jbB2.addActionListener(alButton);
        
        Container cp=getContentPane();
        GridBagLayout gbl=new GridBagLayout();
        cp.setLayout(gbl);
        GridBagConstraints gbc=new GridBagConstraints();    gbc.fill=GridBagConstraints.BOTH;
        gbc.weightx=1.0;
        gbc.weighty=0.0;
        gbc.gridwidth=1;
        gbc.insets=new Insets(5,2,5,2);    cp.add(jbB1);
        cp.add(jbB2);
        setSize(320,320);
        setVisible(true);
        
        mainTimer=new Timer(3000,null);
        mainTimer.addActionListener(alButton);
      }
      public static void main(String args[])
      {
        TestSyn mainFrame=new TestSyn();
      }
      public JButton getButton1()
      {
        return jbB1;
      }
      public JButton getButton2()
      {
        return jbB2;
      }
      public Timer getTimer()
      {
        return mainTimer;
      }
      synchronized public void doButton1()
      {
        mainTimer.start();
        JOptionPane.showConfirmDialog
                (this,"In doButton1","ABC",
            JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
        System.out.println("in doButton1()!");
      }
      public void doButton2()
      {
        System.out.println("in doButton2()!");
      }
      synchronized public void  doTimer()
      {
        System.out.println("in doTimer()!");
        mainTimer.stop();
      }
    }class ButtonListener implements ActionListener
    {
      private TestSyn testsyn;  public ButtonListener(TestSyn ts)
      {
        testsyn=ts;
      }
      public void actionPerformed(ActionEvent e)
      {
        Object eventObject=e.getSource();
        if(eventObject==testsyn.getButton1())
            testsyn.doButton1();
        else if(eventObject==testsyn.getButton2())
            testsyn.doButton2();
        else if(eventObject==testsyn.getTimer())
            testsyn.doTimer();
      }
    }在JBuilder下运行时,发现按下button1后,显示消息框,在不退出消息框的情况下,3秒后依然会显示in doTimer()!信息,这不是synchronized不起作用了吗?还是定时器有什么“特权”?
      

  4.   

    synchronized表示该方法或者该代码段是同步执行的, 也就是A方法是synchronized的话, 同一个时间点, 只可能有一个A方法在被执行. 而同一个类的B方法,不管是不是synchronized或者A是不是在执行都可以被执行.
    你说的问题, 我想应该是JOptionPane显示出来的对话框不是Modal模式的, 因此后台的Timer仍然在反复执行. 如果你换一个Modal方式的JDialog跳出来, 试试看, 在Dialog还没有关掉的情况下是不是doTimer方法仍然被执行呢?
      

  5.   

    楼上的看法是错误的
    synchronized是对方法所在的对象进行同步的,而不是仅仅对方法本身起作用
    及如果a对象的A方法和B方法都是synchronized 那么A和B不可能同时执行lz的程序虽然看上去好像是两个synchronized的方法被同时执行了,但是其实并不是这样
    事实上doTimer()方法是在doButton1()方法中被调用的(当然不是lz主动调用的)
    这是被GUI程序的消息循环控制的 JOptionPane.showConfirmDialog在用户没有点按钮时,程序是处于消息循环中 而不是sleep 当timer事件到来时 消息循环线程 就会调用doTimer方法
    其实doButton1和doTimer都是被消息循环线程调用的
      

  6.   

    在doTimer中添加一句
    new Throwable().printStackTrace();这样就可以看到doTimer方法的调用堆栈,你可以看到doTimer方法是从doButton1方法调用过来的
      

  7.   


    多谢polarman,说得有道理,我看了printStackTrace的输出,确实是doButton1调用过来的,此时相当于从一个同步函数调用另一个同步函数,所以能顺利进入。而且我把mainTimer.start();调用移动到TestSyn的构造函数中,同时把mainTimer.stop();从doTimer中删掉,发现结果是一样的,消息框正在显示时一样会3秒钟输出一次。对这种现象不知有没有什么通用的理论可以描述?或者在什么文章中有描述?