第一遍粗略看三各类,声明了什么变量 , 和写了什么方法名

    首先新建一个类叫树类吧 :下面的方法用synchronized修饰可以一会再看

public class Tree {
    int value;
    public synchronized void Add(){ //不是从方法内部声明的变量才需要锁
        value +=1;
        //只锁以给Add()方法加锁,而不给线程类的run方法加锁,是因为:在线程run方法中加,锁不住value变量  
  }
}


         然后新建一个线程类:

        在这我们在这写了一个线程调用时的run方法,和一个构造方法(可有可无,但是我这用到了)。

            
import javax.naming.Name;
 
public class ThreadTest extends Thread {
    private String name;
    private Tree tree ;
    ThreadTest(String name,Tree tree) {
        this.name = name;
        this.tree = tree;
    }
    // synchronized 只要锁住了Add方法就 不用锁run ,这样的好处是由于此处没加锁_节省效率,<<只锁调用资源的方法就行>>
    public  void run() {
        for (int i = 0; i < 300; ++i){
            System.out.println("====" + name);//输出调用的过程
            tree.Add();//通过锁住Add()方法,来实现锁住value 而不能直接调用 tree.value += 1
            //这里不可以用 tree.value +=1 , 这样是锁不住的,只能锁住tree但是锁不住 tree.value
        }
 
 
    }
 
}


下面是对我们写好的类进行测试,新建了两个线程 t1和 t2 调用线程 。try/catch语句是为了帮助线程先完成再看结果, 
import javax.naming.Name;
 
public class ThreadTest extends Thread {
    private String name;
    private Tree tree ;
    ThreadTest(String name,Tree tree) {
        this.name = name;
        this.tree = tree;
    }
    // synchronized 只要锁住了Add方法就 不用锁run ,这样的好处是由于此处没加锁_节省效率,<<只锁调用资源的方法就行>>
    public  void run() {
        for (int i = 0; i < 300; ++i){
            System.out.println("====" + name);//输出调用的过程
            tree.Add();//通过锁住Add()方法,来实现锁住value 而不能直接调用 tree.value += 1
            //这里不可以用 tree.value +=1 , 这样是锁不住的,只能锁住tree但是锁不住 tree.value
        }
 
 
    }
 
}



下面进行第二遍梳理:

如果你觉得有疑问可以试一下将如下代码段改变,然后多运行几次,你会发现结果是不稳定的,这就说明锁没有把value锁住。

因为 synchronized 只是锁住了 tree 并没锁住 tree.value。 剩下的看一下注释吧
import org.omg.Messaging.SyncScopeHelper;
 
public class TestThread {
    public static void main(String[] args) {
        Tree tree = new Tree();
        tree.value = 0;
        ThreadTest t1 = new ThreadTest("调用线程1",tree);
        ThreadTest t2 = new ThreadTest("调用线程2",tree);
 
        t1.start();
        t2.start();
 
       try {
            t1.join();//这样可以先加入线程再输出值
            t2.join();
       }catch (InterruptedException e){
            e.printStackTrace();
       }
 
        System.out.println(tree.value);//发现变成了我们所期望的600
    }
}