synchronized 对象锁 or 类锁?

来源:互联网 发布:php redis session 编辑:程序博客网 时间:2024/06/09 21:36

最近在看并发编程,把典型demo记录下,作为学习笔记。同时分享给初学者,如有错误,欢迎指出。



关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock), 在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。


以下为demo1:

public class MultiThread {


private int num = 0;

/** static */

public synchronized void printNum(String tag){

try {

if(tag.equals("a")){

num = 100;

System.out.println("tag a, set num over!");

Thread.sleep(1000);

} else {

num = 200;

System.out.println("tag b, set num over!");

}

System.out.println("tag " + tag + ", num = " + num);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//注意观察run方法输出顺序

public static void main(String[] args) {

//俩个不同的对象

final MultiThread m1 = new MultiThread();

final MultiThread m2 = new MultiThread();

Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

m1.printNum("a");

}

});

Thread t2 = new Thread(new Runnable() {

@Override 

public void run() {

m2.printNum("b");

}

});

t1.start();

t2.start();

}


}

打印结果:


把demo1 synchronized 关键字前加static关键字

demo2:

public class MultiThread {


private static int num = 0;

/** static */

public static synchronized void printNum(String tag){

try {

if(tag.equals("a")){

num = 100;

System.out.println("tag a, set num over!");

Thread.sleep(1000);

} else {

num = 200;

System.out.println("tag b, set num over!");

}

System.out.println("tag " + tag + ", num = " + num);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//注意观察run方法输出顺序

public static void main(String[] args) {

//俩个不同的对象

final MultiThread m1 = new MultiThread();

final MultiThread m2 = new MultiThread();

Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

m1.printNum("a");

}

});

Thread t2 = new Thread(new Runnable() {

@Override 

public void run() {

m2.printNum("b");

}

});

t1.start();

t2.start();

}

}

运行结果:


对比运行结果:不加static 关键字,是对象锁,main方法里执行的是2个实例化对象,分别是2把锁,所以同时执行,没有等待;

加了static关键字,是类锁,main方法里2个实例化对象共用同一个类锁,所以必须等待前一个线程执行完,才能执行下一个线程。

原创粉丝点击