关于sychronized锁的一些研究。

来源:互联网 发布:圆方软件购买 编辑:程序博客网 时间:2024/05/21 08:41

一.测试 Thread的wait()和sleep()的方法对于锁的释放

public class Thread1 implements Runnable{


public Thread holdThread;

@Override
public void run() {
System.out.println(holdThread.getName() + " start  to increase()...");
AppleCount.instance.increaseNum(this,holdThread,true);
try {
System.out.println(holdThread.getName() + " start  to sleep 3S...");
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

public class Thread2 implements Runnable{

public Thread holdThread;

@Override
public void run() {
System.out.println(holdThread.getName() + " start  to increase()...");
AppleCount.instance.increaseNum(this,holdThread,false);
}
}

public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread2 t2 = new Thread2();
Thread one = new Thread(t1, "t1");
Thread two = new Thread(t2, "t2");
t1.holdThread = one;
t2.holdThread = two;
one.start();
two.start();
}


A.sleep方法的执行结果:

public class AppleCount {

public static AppleCount instance = new AppleCount();

public  int num;

public synchronized void increaseNum(Runnable r, Thread t, boolean isSleep){
num++;
System.out.println(t.getName() + " into increaseNum().....");
if(isSleep){
try {
System.out.println(t.getName() + " into sleep.....");
t.sleep(3000);
System.out.println(t.getName() + " into sleep end.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " end  increaseNum().....");
}
}

运行结果:

t1 start  to increase()...
t1 into increaseNum().....//t1进入方法块,获得锁
t1 into sleep.....//t1进入了睡眠,但是没有释放锁
t2 start  to increase()...//t2在等待t1的锁,可以看到t1的锁没有释放
t1 into sleep end.....//t1结束睡眠
t1 end  increaseNum().....//t1退出方法块,释放锁
t1 start  to sleep 3S...
t2 into increaseNum().....//t2进入方法块,获得锁
t2 end  increaseNum().....//t2退出方法块,获得锁

TIP:由结果可以看出,线程的sleep方法不会释放锁


B.wait方法的执行结果:

public class AppleCount {

public static AppleCount instance = new AppleCount();

public int num;

public synchronized void increaseNum(Runnable r, Thread t, boolean isSleep){
num++;
System.out.println(t.getName() + " into increaseNum().....");
if(isSleep){
try {
System.out.println(t.getName() + " into sleep.....");
instance.wait(3000);
System.out.println(t.getName() + " into sleep end.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " end  increaseNum().....");
}
}

运行结果:

t1 start  to increase()...
t1 into increaseNum()..... //t1进入方法块,获得锁
t1 into sleep.....//t1进入睡眠,释放了锁
t2 start  to increase()...//t2进入方法块,获得锁
t2 into increaseNum().....
t2 end  increaseNum().....//t2退出方法块,释放锁
t1 into sleep end.....//t1重新获得锁,继续执行
t1 end  increaseNum().....
t1 start  to sleep 3S...


二.测试类锁

public class AppleCount {

public static AppleCount instance = new AppleCount();//静态类

public static int num;

public static synchronized void increaseNum(Runnable r, Thread t, boolean isSleep){
num++;
System.out.println(t.getName() + " into increaseNum().....");
if(isSleep){
try {
System.out.println(t.getName() + " into sleep.....");

//instance.wait(3000) 抛错,类级锁而不是对象锁
instance.getClass().wait(3000);//注意一定要用类的锁释放,不然抛错
//AppleCount.class.wait(3000);//这个也可以
System.out.println(t.getName() + " into sleep end.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " end  increaseNum().....");
}
}


TIP:现在该方法是属于静态同步方法,其锁住的是该类在内存中对应该方法的字节码,一切该类的实例对象都将会被同步,这个锁相当于类级别的锁

故在释放锁时,不能用instance.wait(3000)的方法来释放(这个表明的是对象锁),而应该采用instance.getClass().wait(3000)来释放类锁。


运行结果:

t1 start  to increase()...
t1 into increaseNum().....//t1进入方法块,获得锁
t1 into sleep.....//t1进入睡眠,释放锁
t2 start  to increase()...
t2 into increaseNum().....//t2进入方法块,获得锁
t2 end  increaseNum().....//t2退出方法块,释放锁
t1 into sleep end.....//t1重新获得锁,继续执行
t1 end  increaseNum().....
t1 start  to sleep 3S...

0 0