第一遍粗略看三各类,声明了什么变量 , 和写了什么方法名
首先新建一个类叫树类吧 :下面的方法用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 } }