网上看了一篇关于java synchronized关键字使用的很好的文章,现将其简要总结一下,加深理解。
先总结两个规则:
synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。
多个线程的synchronized必须锁住的是同一个对象,才能防止多个线程同时执行同一个对象的同步代码段。
有两种方法可以实现多个线程锁住的是同一个对象
1.线程中定义相同的成员,成员的值在线程初始化时从外界注入同一个对象。
class Sync {
//写法一
// public void test() {
// synchronized(this){
// System.out.println("test开始..");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println("test结束..");
// }
// }
//写法二,与写法一等效,都是锁住对象sync
public synchronized void test() {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}
class MyThread extends Thread {
private Sync sync;
public MyThread(Sync sync) {
this.sync = sync;
}
public void run() {
sync.test();
}
}
public class Main {
public static void main(String[] args) {
Sync sync = new Sync();
for (int i = 0; i < 3; i++) {
Thread thread = new MyThread(sync);
thread.start();
}
}
}
输出结果:
test开始..
test结束..
test开始..
test结束..
test开始..
test结束..
分析:3个线程MyThread中都定义了成员sync,在初始化线程时,给每个线程的sync赋予了相同的值,即3个线程的sync是同一个实例。启动3个线程以后,synchronized锁住的其实就是this,在当前demo中指的就是sync实例,3个线程的sync是同一个对象,所以3个线程中使用的同一个对象锁,同一时刻只能有一个线程进入test同步方法块。
2.使用类对应的Class作为要锁住的对象,全局锁
class Sync {
public void test() {
synchronized (Sync.class) {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}
}
class MyThread extends Thread {
public void run() {
Sync sync = new Sync();
sync.test();
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
输出结果:
test开始..
test结束..
test开始..
test结束..
test开始..
test结束..
分析:类对应的Class对象作为锁的目标,确保锁住的是同一个对象。