当类中一个方法被使用synchronized关键字修饰时,含义是这个方法被锁定,或者说这个代码段被锁定,并非这个方法中所用的变量被锁定。下面首先看第一个例子,例子中在被synchronized修饰的方法中修改某个类变量并睡眠一段时间,期间在其他线程中打印该变量,这个变量可以正确的显示,也就是说变量并没有被锁死。
package ttt;
public class testtt9 implements Runnable {
public int num = 0;
public synchronized void run() {
try {
//修改成员变量并休眠。
num = 1;
Thread.sleep(3000);
System.out.println(num);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
testtt9 t9=new testtt9();
Thread th=new Thread(t9);
th.start();
//在主线程中打印被修改的成员变量,休眠10毫秒是为了保证线程th已经开始执行。
Thread.sleep(10);
System.out.println(t9.num);
}
}
执行结果是两个1,也就是说成员变量没有因为
public synchronized void run()
的缘故而被锁住。那synchronized修饰类方法的含义到底是什么呢?synchronized修饰类方法的作用实际上是锁死了这个方法,即在同一时间内,只能有一个线程可以调用这个方法,因为我们知道一个类对象可以被装入多哥不同的Thread线程中同时操作,如果这个方法被synchronized修饰,那同时只能有一个方法被调用,下面看一个简单的例子。
package ttt;
public class testtt9 implements Runnable {
public int num = 0;
public synchronized void run() {
num++;
try{
Thread.sleep(3000);
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
testtt9 t9=new testtt9();
Thread th1=new Thread(t9);
Thread th2=new Thread(t9);
//线程th1,th2都试图令num的值加1,两个线程同时进行,当会休眠3秒。
th1.start();
Thread.sleep(1);
th2.start();
Thread.sleep(1);
//打印修改后的结果。
System.out.println(t9.num);
Thread.sleep(4000);
System.out.println(t9.num);
}
}
输出的结果为1,2。也就是说只有th1和th2的run方法中的内容并非同时进行,而是分前后的,因为方法被synchronized修饰了。如果去掉synchronized关键字,输出的结果为2,2。