大家好,在多线程中使用synchonized声明的方法为同步方法后,当多个线程进入对象,只有取得该对象钥匙的线程才可以访问同步方法,其它线程在该对象中等待,直到该线程用wait()方法放弃这把钥匙,其它等待的线程抢占该钥匙,抢占到钥匙的线程后才可得以执行,而没有取得钥匙的线程仍被阻塞在该对象中等待。但是不是非要等到得到的锁的线程将方法体执行完后,其他线程才能进入执行呢?请看如下程序
 class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public synchronized void run(){
        System.out.println(this.getName() + "   is start**************************");
           while(shareVar < 10){ 
                    shareVar++;
                System.out.println(this.getName() + " :sharVar is "+ shareVar + "\n");     
            }
             System.out.println(this.getName() + "   is end-----------------------" + "\n\n");
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            TestThreadMethod t2 = new TestThreadMethod("t2");
            t1.start();
            t2.start();
        }
}
--------------------------------------------------------------------------
执行结果如下:
t1   is start************************
t1 :sharVar is 1t1 :sharVar is 2t1 :sharVar is 3t1 :sharVar is 4t1 :sharVar is 5t1 :sharVar is 6t1 :sharVar is 7t2   is start************************
t2 :sharVar is 8t2 :sharVar is 9t2 :sharVar is 10t2   is end-----------------------
t1   is end-----------------------按照上面的说法,每个线程释放锁之前都至少应该答应 is end---------这句啊,为什上面的结果不是
t1   is start************************
t1 :sharVar is 1t1 :sharVar is 2t1 :sharVar is 3t1 :sharVar is 4t1 :sharVar is 5t1 :sharVar is 6t1 :sharVar is 7t2   is end-----------------------
t2   is start************************
t2 :sharVar is 8t2 :sharVar is 9t2 :sharVar is 10t1   is end-----------------------
先在此谢谢大家了!

解决方案 »

  1.   

    对不起,些错的,结果为什么不是
    t1   is start************************ 
    t1 :sharVar is 1 t1 :sharVar is 2 t1 :sharVar is 3 t1 :sharVar is 4 t1 :sharVar is 5 t1 :sharVar is 6 t1 :sharVar is 7 t1   is end----------------------- 
    t2   is start************************ 
    t2 :sharVar is 8 t2 :sharVar is 9 t2 :sharVar is 10 t2   is end----------------------- 
      

  2.   

    t1和t2是二个对象,怎么锁?t1的同步锁只能锁t1,不能锁t2
      

  3.   

    1.可以把while循环看做一条语句,如果线程执行时没有发生意外的情况下,应该先把while循环语句执行完再执行
      System.out.println(this.getName() + "   is end-----------------------" + "\n\n") 吧
    2.楼主的synchronized方法用不用好象对执行结果并无影响啊.synchronized方法应该用在共享同一个对象时吧.
      

  4.   

    你把run()里的内容写到TestThreadMethod外面去 然后在run()里面调用 你就明白了
      

  5.   

    我把run()里的内容写到TestThreadMethod外面去 然后在run()里面调用了啊,但结果一样,还有啊,如果照上面的程序,run进行同步后,应该只有第一个线程进入打印,第二个线程没有机会打印啊,因为shareVar已经大于10了啊,synchonized到底是怎么个加锁和解锁啊,有没有图示,用一个图来形象解释下
      

  6.   

    我把run()里的内容写到TestThreadMethod外面去 然后在run()里面调用了啊,但结果一样
      

  7.   

    synchronized  是一个对象锁!!  也就是说同一个对象的 synchronized 方法  只能在同一时间被一个线程访问!!!可是你的 例子是 t1 和 t2 两个对象! 
    你改成这样: 结果为什么是这样 你自己想下就是了import java.io.File;
    import java.io.FileInputStream;
    import java.util.Properties;class TestThreadMethod extends Thread { public TestThread tt = null;
    public TestThreadMethod(String name, TestThread tt) {
    super(name);
    this.tt = tt;
    } public void run() {
    tt.print(this.getName());
    }
    }public class TestThread {
    public volatile static int shareVar = 0; public synchronized void print(String name) {
    try { System.out.println(name
    + "   is start**************************");
    while (shareVar < 10) {
    shareVar++;
    System.out.println(name + " :sharVar is "+ shareVar + "\n");      
    Thread.sleep(100);
    }
    System.out.println(name
    + "   is end-----------------------" + "\n\n");
    } catch (Exception e) {
    // TODO: handle exception
    }
    }

    public static void main(String[] args) {
    TestThread tt = new TestThread();
    TestThreadMethod t1 = new TestThreadMethod("t1", tt);
    TestThreadMethod t2 = new TestThreadMethod("t2", tt);
    t1.start();
    t2.start();
    }
    }
     
    结果
    t1   is start**************************
    t1 :sharVar is 1t1 :sharVar is 2t1 :sharVar is 3t1 :sharVar is 4t1 :sharVar is 5t1 :sharVar is 6t1 :sharVar is 7t1 :sharVar is 8t1 :sharVar is 9t1 :sharVar is 10t1   is end-----------------------
    t2   is start**************************
    t2   is end-----------------------
      

  8.   

    看不太明白你的意思,
    不过你明白wait()是什么意思吗,
    synchronized方法是对this进行加锁的,
    不管是对什么对象加锁,当synchronized块被执行完后都会自动解锁,而wait()方法也锁是为了更好的利用CPU,java就在你等待的时间里让它解锁(暂时),
    等它再次启动的时候它得到CPU使用的权根是很高的。
      

  9.   


    public class Test 
    {
        public static void main(String[] args)throws Exception
        {
            TestThreadMethod t1 = new TestThreadMethod("t1"); 
            TestThreadMethod t2 = new TestThreadMethod("t2"); 
            t1.start(); 
            t2.start(); 
        }
    }
    class TestThreadMethod extends Thread{     
        public TestThreadMethod(String name){ 
            super(name); 
        } 
        TestThread t=new TestThread();
        public void run(){ 
         t.run(this.getName());
        } 

    class TestThread{ 
    public static int shareVar = 0;
        public synchronized  void run(String name){ 
         System.out.println(name + "   is start**************************"); 
            while(shareVar  < 10){  
                     shareVar++; 
                 System.out.println(name + " :sharVar is "+ shareVar + "\n");      
             } 
              System.out.println(name + "   is end-----------------------" + "\n\n"); 
        }
    } t1   is start**************************
    t1 :sharVar is 1t1 :sharVar is 2t1 :sharVar is 3t1 :sharVar is 4t1 :sharVar is 5t1 :sharVar is 6t1 :sharVar is 7t1 :sharVar is 8t1 :sharVar is 9t1 :sharVar is 10t1   is end-----------------------
    t2   is start**************************
    t2   is end-----------------------
      

  10.   

    把方法变成静态方法好像也可以哟
    package com.qijian.test;class TestThreadMethod extends Thread {
    public static int shareVar = 0; public TestThreadMethod(String name) {
    super(name);
    } static String s = "   is start-----------------------";
    static String e = "   is end  -----------------------"; public synchronized static void e() throws InterruptedException {
    //      System.out.println(this.getName() + s);  
    System.out.println(Thread.currentThread().getName()
    + "Thread is start-----------------------");
        while(shareVar < 10){  
    shareVar++;
    //        System.out.println(this.getName() + " :sharVar is "+ shareVar + "\n");   
    System.out.println(Thread.currentThread().getName() + ":" + shareVar);
    //    if(shareVar == 5)Thread.currentThread().wait();
         } 
    //    System.out.println(this.getName() + e + "\n\n");       
    System.out.println(Thread.currentThread().getName()
    + ": :Thread  is End>>>>>>>>>----end---<<<<<----------------");
    } public void run() {

    try {
    e();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } }
    }public class TestThread {
    public static void main(String[] args) {
    TestThreadMethod t1 = new TestThreadMethod("t1");
    TestThreadMethod t2 = new TestThreadMethod("t2");
    t1.start();
    t2.start();
    }
    }
      

  11.   

    用10楼的方法,只要将循环定大些还是出现了我原先那种现象,如我定为1000
    package com.qijian.test;public class Test 
    {
        public static void main(String[] args)throws Exception
        {
            TestThreadMethod t1 = new TestThreadMethod("t1"); 
            TestThreadMethod t2 = new TestThreadMethod("t2"); 
            t1.start(); 
            t2.start(); 
        }
    }
    class TestThreadMethod extends Thread{     
        public TestThreadMethod(String name){ 
            super(name); 
        } 
        TestThread t=new TestThread();
        public void run(){ 
            t.run(this.getName());
        } 

    class TestThread{ 
        public static int shareVar = 0;
        public synchronized  void run(String name){ 
            System.out.println(name + "   is start**************************"); 
            while(shareVar  < 1000){  
                     shareVar++; 
                 System.out.println(name + " :sharVar is "+ shareVar + "\n");      
             } 
              System.out.println(name + "   is end-----------------------" + "\n\n"); 
        }

    ---------------------------------------------------------
    部分结果如下:
    t2 :sharVar is 991t2 :sharVar is 992t2 :sharVar is 993t2 :sharVar is 995t2 :sharVar is 996t2 :sharVar is 997t2 :sharVar is 998t2 :sharVar is 999t2 :sharVar is 1000t2   is end-----------------------
    t1 :sharVar is 994t1   is end-----------------------
      

  12.   

    public synchronized void print(String name) {
            try {            System.out.println(name
                        + "   is start**************************");
                while (shareVar < 10) {
                    shareVar++;
                    System.out.println(name + " :sharVar is "+ shareVar + "\n");      
                    Thread.sleep(100);
                }
                System.out.println(name
                        + "   is end-----------------------" + "\n\n");
            } catch (Exception e) {
                // TODO: handle exception
            }
    public synchronized void print (String userName)
    {
    try
    {
    while(sgareVar <10)
    {
        shareVar++;
        S
    }
    }
    }
      

  13.   


    因为
    class TestThreadMethod extends Thread{      
        public TestThreadMethod(String name){  
            super(name);  
        }  
        TestThread t=new TestThread();  //这里还是创建了2个t 哈哈 把这行注释掉
        public void run(){  
            t.run(this.getName()); 
        }  
    }  
    class TestThread{  
        public static int shareVar = 0; 
        public synchronized  void run(String name){   //把这个run改成静态的应该就不会有问题了吧 或者你用8楼的方法吧  反正设置成2个线程访问同一个对象就不会有问题了 
            System.out.println(name + "   is start**************************");  
            while(shareVar   < 1000){   
                     shareVar++;  
                 System.out.println(name + " :sharVar is "+ shareVar + "\n");       
             }  
              System.out.println(name + "   is end-----------------------" + "\n\n");  
        } 
    }  
      

  14.   

     知道了,我已经知道哪里出错了,但对synchronized的加锁模型在头脑不是很明朗,我头脑中的建模是这样的:共享资源对象有个门,这个门上有个门栓,而每个对象都有个锁(监视器),当一个线程对象访问这个共享资源时,他就把自己的锁,锁到门栓上,等他执行完后,他将他的锁拿掉,其他线程对象继续重复此过程。这里一个关键是我认为每个对象都用各自的锁锁门然后拿掉自己的锁,这点不知道我理解的对不对?