如图所示在编译中使用synchronized关键字之后出现了只有线程Thread-0运行而不见Thread-1 请问是正常情况还是代码出错 求解答
关键字synchronized还可以修饰静态方法,如果修饰静态方法,那就表示给当前Java类进行上锁(也就是Class)。
用法实例:
锁静态代码块:
public static void testSyncStaticBlock() {
synchronized (SyncStaticTest.class) {
System.out.println("锁静态代码块");
}
}
锁静态方法:
synchronized public static void testSyncStaticMethod() { System.out.println("锁静态方法"); }
给Class类上锁和给this对象上锁是有本质不同的,举个例子说明一下:
条件:
假设有一个Java类ClassA, 里面定义了synchronized修饰的静态方法staticMethodA, 和非静态方法methodB。
用ClassA 创建两个实例ClassObjA 和 ClassObjB。
创建两个线程threadA和threadB。
实验:
1. 用threadA调用classObjA的methodB方法,同时用threadB调用classObjB的methodB方法,发现执行并不是同步的,因为在动态方法中,实例classObjeA的methodB方法的this是指的classObjA,classObjeB的methodB方法this是指的classObjB,上面反复提到过,我们一定要弄清楚对象监视器的指针是指向谁,这很明显是两个对象,压根不存在对象争抢的问题,所以当然不会同步执行。
2. 用threadA和threadB都调用ClassA.staticMethodA方法, 发现是同步执行的,因为synchronized锁的是静态代码块,所以跟对象就没什么关系了,不管哪个线程,只要你调用我ClassA的这个静态方法,都必须排队。
上面两个实验可以很清晰的看到锁class静态代码块和锁对象的区别。
插个广告:下节我们将介绍volatile的各种用法。
参考:
《Java多线程核心技术》高洪岩著
只有Thread-0线程运行而没有Thread-1线程运行并不是正常现象,很可能是代码出现了问题。使用synchronized关键字可以修饰代码块,形如synchronized(锁对象){...},synchronized关键字需要一个锁对象作为参数,所以每个线程需要拥有该锁对象来进入synchronized代码块。参考资料中的代码中,使用this作为锁对象,每个线程都独立创建了一个Runnable实例,因此锁对象也不同,这违反了使用synchronized关键字的初衷。解决的办法是使用同一个锁对象,比如可以使用static修饰一个Object类型的变量来作为锁对象,示例代码如下:
static int n = 0;
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
synchronized (lock) {
n++;
}
}
}
};
new Thread(r).start();
new Thread(r).start();
Thread.sleep(3000);
System.out.println(n);
}
在这个代码中,使用static Object类型的变量lock作为锁对象,每个线程都使用同一个锁,这样就可以保证两个线程都能够访问synchronized代码块。