class Test2 
{
public Test2(int id)
{
MyThread2 test1 = new MyThread2(id);
test1.start();
}
class MyThread2 extends Thread
{
int id=0;
public MyThread2(int id)
{
this.id=id;
}
public void run()
{
synchronized(this)
{
for(int i=0;i++<50;)
System.out.println("id = "+id);
}
}
}
}
class Test3
{
public static void main(String[] args)
{
Test2 test = new Test2(1);
Test2 test2 = new Test2(2);
}
}我看到有个例子是这样用的,但我试了一下,好像不对.
请问synchronized(this)该怎么用?我不大懂.
上例中的this指的是Test2对象,还是MyThread2对象?

解决方案 »

  1.   

    哪个对象在调用run,就指的是哪个对象了! 和一般的this没什么区别!
      

  2.   

    如果要用synchronized(this)实现同步该怎么做呢?能给个简单的例子吗?谢谢
      

  3.   

    给你个thinking in java里面的例子吧! 很长 !关键段
    有时你只需要防止多个线程同时访问方法中的某一部分,而不是整个方法。这种需要隔离的代码就被称为关键段(critical section)。创建关键段需要用到synchronized关键词。这里,synchronized的作用是,指明执行下列代码需获得哪个对象的锁。synchronized(syncObject) {
      // This code can be accessed 
      // by only one thread at a time
    }关键段又被称为"同步块(synchronized block)";线程在执段代码之前,必须先获得syncObject的锁。如果其它线程已经获得这个锁了,那么在它解锁之前,线程不能运行关键段中的代码。同步分两种,代码的同步和方法的同步。下面这段例程比较了这两种方案。通过对比可以看出,相比同步整个方法,同步一段代码能显著增加其它线程获得这个对象的机会。此外,它还演示了如何用wrapper使用和保护非线程安全的类://: c13:CriticalSection.java
    // Synchronizing blocks instead of entire methods. Also
    // demonstrates protection of a non-thread-safe class
    // with a thread-safe one.
    import java.util.*;
    class Pair { // Not thread-safe
      private int x, y;
      public Pair(int x, int y) {
        this.x = x;
        this.y = y;
      }
      public Pair() { this(0, 0); }
      public int getX() { return x; }
      public int getY() { return y; }
      public void incrementX() { x++; }
      public void incrementY() { y++; }
      public String toString() {
        return "x: " + x + ", y: " + y;
      }
      public class PairValuesNotEqualException
      extends RuntimeException {
        public PairValuesNotEqualException() {
          super("Pair values not equal: " + Pair.this);
        }
      }
      // Arbitrary invariant -- both variables must be equal:
      public void checkState() {
        if(x != y)
          throw new PairValuesNotEqualException();
      }
    }
    // Protect a Pair inside a thread-safe class:
    abstract class PairManager {
      protected Pair p = new Pair();
      private List storage = new ArrayList();
      public synchronized Pair getPair() {
        // Make a copy to keep the original safe:
        return new Pair(p.getX(), p.getY());
      }
      protected void store() { storage.add(getPair()); }
      // A "template method":
      public abstract void doTask();
    }
    // Synchronize the entire method:
    class PairManager1 extends PairManager {
      public synchronized void doTask() {
        p.incrementX();
        p.incrementY();
        store();
      }
    }
    // Use a critical section:
    class PairManager2 extends PairManager {
      public void doTask() {
        synchronized(this) {
          p.incrementX();
          p.incrementY();
        }
        store();
      }
    }
    class PairManipulator extends Thread {
      private PairManager pm;
      private int checkCounter = 0;
      private class PairChecker extends Thread {
        PairChecker() { start(); }
        public void run() {
          while(true) {
            checkCounter++;
            pm.getPair().checkState();
          }
        }
      }
      public PairManipulator(PairManager pm) {
        this.pm = pm;
        start();
        new PairChecker();
      }
      public void run() {
        while(true) {
          pm.doTask();
        }
      }
      public String toString() {
        return "Pair: " + pm.getPair() +
          " checkCounter = " + checkCounter;
      }
    }
    public class CriticalSection {
      public static void main(String[] args) {
        // Test the two different approaches:
        final PairManipulator
          pm1 = new PairManipulator(new PairManager1()),
          pm2 = new PairManipulator(new PairManager2());
        new Timer(true).schedule(new TimerTask() {
          public void run() {
            System.out.println("pm1: " + pm1);
            System.out.println("pm2: " + pm2);
            System.exit(0);
          }
        }, 500); // run() after 500 milliseconds
      }
    } ///:~
    你也看到了,Pair不是一个线程安全的类,它的invariant(我们随便定了一个)要求X和Y的值相同。此外,正如我们前面所看到的,递增不是线程安全的操作,而这些方法也都不是synchronized的,所以在多线程环境下,Pair肯定会出问题。PariManager包含一个Pair对象,与此同时它还控制了外部对这个对象的所有访问。注意,它的两个public方法,getPair( )和abstract doTash( )都是synchronized。只是后者的同步化处理放到了实现里面。PairManager的功能,有的是在abstract的基类里实现的,有的是在派生类里定义的。用设计模式的话来说,这就是是Template Method。[71]设计模式要求你把会变的代码封装起来;这里会变的就是模板方法doTask( )。PairManager1把整个doTask( )同步化了,而PairManager2用关键段部分地同步化了这个方法。注意,synchronized关键词不属于方法的特征签名,因此覆写的时候可以加上去。PairManager2值得关注。store( )是一个protected方法,也就是说只有子类才能访问,一般的客户根本是看不到的。所以我们就无需再把它放到synchronized方法里了。这里它被置于关键段之外。关键段必须要有对象来同步,最常见的就是这个方法自己所属的对象:synchronized(this)。PairManager2就用了这个方法。这样,当关键段获得对象锁的时候,其他线程就不能调用这个对象的synchronized方法了。而这样做的效果就是,大大缩小了同步的范围
      

  4.   

    class Test2 里面加个private static Object obj = new Object();
    然后synchronized(this)改成synchronized(obj)就OK了
      

  5.   

    哦~~~可以用synchronized()指明具体方法啊
      

  6.   

    synchronized拿来修饰方法也可以啊!
      

  7.   

    此文章的目的在于利用线程的互斥,解决生产者消费者问题。其中使用了关键字sychronized。线程的内容可以一样,但是对应不同的内存地址。运行起来相互独立,是两个完全独立的进程。producer.java文件:package ProducerConsumer;
    class Producer extends Thread
    {
      CircularBuffer cbp=null;
     
     
     Producer(CircularBuffer cb){cbp=cb;}
     public void run(){
      for(int i=0;i<=50000;i++)
      try{
       cbp.put(i);
      }
      catch (Exception err){
       //System.
       
       }
      
      }
     // public static void main(String[] args) {}
    }
    ProCum文件:package ProducerConsumer;
    import java.io.*;
    class ProCum{
     public static void main(String[] args){
     
     CircularBuffer cb=new CircularBuffer(20);
     
     //因为要调用的两个方法put和get是排斥,所以调用时由同一个对象调用,所以
     //都是cb,注意注意!!!!!!
     
     Producer pro=new Producer(cb);
     Consumer con=new Consumer(cb);
    // 
     Thread a=null;
     Thread b=null;
      
      a=new Thread(pro);
      
      b=new Thread(con);
      b.start();
      a.start();
     
      }
     }Consumer.java文件:package ProducerConsumer;
    class Consumer extends Thread
    {
     CircularBuffer cbc=null;
     
     
     Consumer(CircularBuffer cb)
     {cbc=cb;}
     public void run(){
      for(int i=0;i<=50000;i++)
      try{
       cbc.get();
      }
      catch (Exception err){
       
       }
      
      }
     
    }
    CircularBuffer.java 文件:package ProducerConsumer;
    import java.io.*;
    class CircularBuffer
    {
     int bufsize;
     int[] store;
     int numOfEntries=0;
     int front=0;
     int back=0;
     
     CircularBuffer(int n)
     {
      bufsize=n;
      store=new int[bufsize];
     
     }
     synchronized void put(int obj)throws Exception{
      if(numOfEntries==bufsize) 
      {
       System.out.println("Producer waiting");
       
       wait();
       
      }
      store[back]=obj;
      back++;
      if(back==bufsize)  back=0;
      else {numOfEntries++;
      System.out.println("putting   "+   obj);
     
      notify();
     }
      
     }
     
     synchronized int get() throws Exception{
      int result=0;
      if(numOfEntries==0)
      {
       System.out.println("Consumer waiting");
       wait(); 
      }  
     
      else{
       result=store[front];
       front++;
       if(front==bufsize) front=0;
       
       
       
        numOfEntries--;
       System.out.println("getting   "+result);//;
       notify();
    }
      return result;
      
      
      
     }
     
     public static void main(String[] args)
     {
    }
     }
      

  8.   

    还用你的例子吧,修改一下.synchronized块是将一个任意的对象加上一把锁,使其他进程在锁未打开的时候不能执行synchronized块中的代码。
    class Test2 
    {
    public Test2(int id)
    {
    MyThread2 test1 = new MyThread2(id);
    test1.start();
    }
    class MyThread2 extends Thread
    {
    int id=0;
    public MyThread2(int id)
    {
    this.id=id;
    }
    public void run()
    {
                               Object obj=new Object();
    synchronized(obj)
    {
    for(int i=0;i++<50;)
    System.out.println("id = "+id);
    }
    }
    }
    }
    class Test3
    {
    public static void main(String[] args)
    {
    Test2 test = new Test2(1);
    Test2 test2 = new Test2(2);
    }
    }
      

  9.   

    你这个例子可以说没有测试到synchronized
      

  10.   

    你这个例子 并没有用到synchronized
    你创建了2个MyThread2对象 并不是一个 
    2个MyThread2对象各拥有自己的字段和方法互不影响
      

  11.   

    class Test2 
    {
          static  synchronized void pp(int id){
                                    for(int i=0;i++<10;){
    System.out.println(i+"          "+"id = "+id);}
                                  } public Test2(int id)
    {
    MyThread2 test1 = new MyThread2(id);
    test1.start();
    }
    class MyThread2 extends Thread
    {
    int id=0;
    public MyThread2(int id)
    {
    this.id=id;
    }
    public  void run()
    {       pp(id);
    //synchronized(this)
    //{

    //}
    }
    }
    }
    public class Test3
    {
    public static void main(String[] args)
    {
    Test2 test = new Test2(1);
    Test2 test2 = new Test2(2);
                     Test2 test3 = new Test2(3);
    }
    }
    同意楼上意见
    楼主可参考此例加以理解
      

  12.   

    楼主的例子根本不需要使用synchronize