一、synchronized关键字
synchronized锁的是什么?
锁对象
可能锁的对象包括:this, 临界资源对象,Class类对象
1.1 同步方法
synchronized T methodName(){}
同步方法锁的是当前对象。当多线程通过同一个对象引用多次调用当前同步 方法时,需同步执行。
public class SynchronizedTest {
public synchronized void synTest() {
System.out.println(Thread.currentThread().getName() + ":synTest() ==> start");
// 模拟业务 等待5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":synTest() ==> end");
}
public static void main(String[] args) {
SynchronizedTest syn = new SynchronizedTest();
int size = 2;
List<Thread> list = new ArrayList<Thread>(size);
for (int i = 0; i < size; i++) {
list.add(new Thread(() -> {
syn.synTest();
},"线程"+i));
}
list.stream().forEach(thread -> {
thread.start();
});
}
}
执行结果
线程0:synTest() ==> start
线程0:synTest() ==> end
线程1:synTest() ==> start
线程1:synTest() ==> end
从结果可以看出线程1需要等待线程0执行完毕才能开始执行。锁的实现参考java内存模型。同理在同一个对象调用不同的同步方法时同样需同步执行。
public class SynchronizedTest {
public synchronized void synTest1() {
System.out.println(Thread.currentThread().getName() + ":synTest1() ==> start");
// 模拟业务 等待5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":synTest1() ==> end");
}
public synchronized void synTest2() {
System.out.println(Thread.currentThread().getName() + ":synTest2() ==> start");
// 模拟业务 等待5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":synTest2() ==> end");
}
public static void main(String[] args) {
SynchronizedTest syn = new SynchronizedTest();
int size = 2;
List<Thread> list = new ArrayList<Thread>(size);
list.add(new Thread(() -> {
syn.synTest1();
}, "线程1"));
list.add(new Thread(() -> {
syn.synTest2();
}, "线程2"));
list.stream().forEach(thread -> {
thread.start();
});
}
}
执行结果
线程1:synTest1() ==> start
线程1:synTest1() ==> end
线程2:synTest2() ==> start
线程2:synTest2() ==> end
为什么说同步方法锁的是当前对象而不是Class对象呢!
public class SynchronizedTest {
public synchronized void synTest1() {
System.out.println(Thread.currentThread().getName() + ":synTest1() ==> start");
// 模拟业务 等待5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":synTest1() ==> end");
}
public synchronized void synTest2() {
System.out.println(Thread.currentThread().getName() + ":synTest2() ==> start");
// 模拟业务 等待5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":synTest2() ==> end");
}
public static void main(String[] args) {
SynchronizedTest syn = new SynchronizedTest();
SynchronizedTest syn1 = new SynchronizedTest();
int size = 2;
List<Thread> list = new ArrayList<Thread>(size);
list.add(new Thread(() -> {
syn.synTest1();
}, "线程1"));
list.add(new Thread(() -> {
syn1.synTest2();
}, "线程2"));
list.stream().forEach(thread -> {
thread.start();
});
}
}
执行结构
线程2:synTest2() ==> start
线程1:synTest1() ==> start
线程1:synTest1() ==> end
线程2:synTest2() ==> end
分析上面的案例如果同步方法锁对是Class对象执行结构就不会出现线程1和线程2同时执行的情况。