考虑如下情景:
一个class 中有一个成员变量b。
成员方法m1()为同步方法, 并且对b进行操作。
成员方法m2()不是同步方法,并且访问b。
那么如果在m1() 锁住b时 , m2()能够执行吗?
如果能 , 得到的b是修改前的还是修改后的呢?
如果m2()也是同步方法呢?
将上诉问题代码化如下, 当m2()不是同步方法时:
package thread;
public class Test implements Runnable{
private int b =100;
public synchronized void m1(){
b=1000;
try{
Thread.sleep(5000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("b="+b);
}
public void m2()
{
System.out.println(b);
}
public void run(){
m1();
}
public static void main(String[] args){
Test test=new Test();
Thread t=new Thread(test);
t.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
test.m2();
}
}
此情境下,以test初始化的线程t先执行了run方法(m1), 然后主线程睡眠1秒(保证b已经被锁住并改变成1000),之后以调用方式执行test的m2()方法。
可能发生的情况有以下几种:
1, 报错
2 , 先打印 b=1000 , 再打印1000 。
说明m1()执行时m2()无法执行(m2()等m1()睡眠5秒结束后才执行)
3 , 先打印 100,再打印b=1000
说明m1锁住b的5秒内,m2()仍然可以访问b, 得到的是b修改前的值
4 先打印 100,再打印b=1000
说明m1锁住b的5秒内,m2()仍然可以访问b, 得到的是b修改后的值
实际上,得到的结果如下:
1000
b=1000
说明当用synchronized修饰的方法执行时, 普通的方法时仍然可以访问synchronized 方法中的变量的。
那么如果 m2()也被synchronized修饰呢?
package thread;
public class Test implements Runnable{
private int b =100;
public synchronized void m1(){
b=1000;
try{
Thread.sleep(5000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("b="+b);
}
public synchronized void m2()
{
System.out.println(b);
}
public void run(){
m1();
}
public static void main(String[] args){
Test test=new Test();
Thread t=new Thread(test);
t.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
test.m2();
}
}
结果是这样的:
b=1000
1000
m1()执行完毕后,m2()才能够执行。