同步方法也可以控制对类成员变量的访问。每个类的实例对象都对应这一把锁,每个同步方法都必须在获得该类实例对象的锁才能执行,方法一旦被执行,就独占该锁,而其他的线程只能等待,知道从该方法返回时才将锁释放。
关键字synchronized用于在多个线程之间同步,当有一个线程进入了有synchronized修饰的方法时,其他线程就不能进入同一个对象使用synchronized来修饰的所有方法,直到第一个线程执行完它所进入的synchronized修饰的方法为止。
package Thread;
public class ThreadDemo {
public static void main(String[] args) {
ThreadTest1 t1=new ThreadTest1();//创建TheadTest1类的实例对象
new Thread(t1).start();//创建线程并启动它
new Thread(t1).start();//创建线程并启动它(原书代码没有添加)
System.out.println(t1.call());//调用ThreadTest1类的同步方法call()
}
}
class ThreadTest1 implements Runnable{
private int x;
private int y;
//定义ThreadTest1的同步方法
public synchronized void run(){//重写Runnable接口的run(),并声明成synchronized
for (int i = 0; i < 4; i++) {
x++;
y++;
try {
Thread.sleep(200); //当前运行的线程休眠200毫秒
} catch (Exception e) {
System.out.println("线程出错了");
}
System.out.println(Thread.currentThread().getName()+" x=" + x+",y="+ y+ " "+i);
}
}
public synchronized String call(){
String name=Thread.currentThread().getName();
return "Hellow "+ name;
}
}
运行截图
解读代码
(1)原书中缺少了一段代码
new Thread(t1).start();//创建线程并启动它(原书代码没有添加)
(2)从这段代码的结果中,从代码的打印顺序上可以看出Thread-0访问完run()后,Thread-1才进入synchronized run()进行数据操作。在Threa-0休眠的时间内,Thread-1也没有进入运行状态。直到Thread-0从synchronized run()方法中返回把锁交给Thread-
(3)对于在main方法中调用的call函数在Thread-0和Thread-1没有访问数据的时候,也没有发生调用。即在Thread-1没把锁叫出来之前,t1.call也只能等待
线程的同步很好的解决了多个线程共同访问同一片存储区域空间发生冲突的问题。