synchronized 是一个关键字。
synchronized 加到 static 方法前面是给class 加锁,即类锁;
synchronized 加到非静态方法上是给对象上锁,即对象锁。
对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。
所以我们用代码来演示下
首先准备工作,先创建一个Task类 新建三个方法其中两个 是static修饰静态的。
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 1:37 下午
* @Version: 1.0
*/
public class Task {
public synchronized static void TaskA() {
System.out.println("ClassName = " + Thread.currentThread().getName() + ", begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ClassName = " + Thread.currentThread().getName() + ", end");
}
public synchronized static void TaskB() {
System.out.println("ClassName = " + Thread.currentThread().getName() + ", begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ClassName = " + Thread.currentThread().getName() + ", end");
}
public synchronized void TaskC() {
System.out.println("ClassName = " + Thread.currentThread().getName() + ", begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ClassName = " + Thread.currentThread().getName() + ", end");
}
第二步 创建三个类来调用各自Task中的方法(也就像IG baolan说:“各过各的”)咱们各调各的。
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 2:00 下午
* @Version: 1.0
*/
public class ThreadA extends Thread{
private Task TTask;
public ThreadA(Task tk){
TTask = tk;
}
public void run() {
TTask.TaskA();
}
}
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 1:46 下午
* @Version: 1.0
*/
public class ThreadB extends Thread{
private Task TTask;
public ThreadB(Task tk){
TTask = tk;
}
public void run() {
TTask.TaskB();
}
}
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 2:01 下午
* @Version: 1.0
*/
public class ThreadC extends Thread{
private Task TTask;
public ThreadC(Task tk){
TTask = tk;
}
public void run() {
TTask.TaskC();
}
}
第三步创建一个main方法咱们来测试一下
public static void main(String[] args) {
Task TTask = new Task();
ThreadA ta = new ThreadA(TTask);
ThreadB tb = new ThreadB(TTask);
ThreadC tc = new ThreadC(TTask);
ta.setName("A");
tb.setName("B");
tc.setName("C");
ta.start();
tb.start();
tc.start();
}
结果如下,我们可以清楚的看到TaskA和TaskB是顺序执行的,而TaskC是和TaskA、TaskB异步执行的。因为TaskA、TaskB是加了static修饰的属于类锁,TaskC是对象锁。
我们来继续测试,测试同步调用TaskC 看看TaskC会不会顺序执行,我们修改ThreadA和ThreadB,让这两个都去调用TaskC方法
然后咱们main也要改下如下
public static void main(String[] args) {
Task TTaska = new Task();
Task TTaskb = new Task();
ThreadA ta = new ThreadA(TTaska );
ThreadB tb = new ThreadB(TTaskb );
ta.setName("A");
tb.setName("B");
ta.start();
tb.start();
}
结果如下,可以看出 ThreadA和ThreadB在调用方法锁TaskC时是异步执行的。
测试完了方法锁,咱们在试试类锁
将ThreadA和ThreadB中调用方法都改成调用TaskA。mian方法不用变执行即可。
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 2:00 下午
* @Version: 1.0
*/
public class ThreadA extends Thread{
private Task TTask;
public ThreadA(Task tk){
TTask = tk;
}
public void run() {
TTask.TaskA();
}
}
/**
* @Title: dmdemo
* @Description:
* @author: liaryank
* @Date: 2020/7/23 1:46 下午
* @Version: 1.0
*/
public class ThreadB extends Thread{
private Task TTask;
public ThreadB(Task tk){
TTask = tk;
}
public void run() {
TTask.TaskA();
}
}
执行结果如下,从结果我们可以看出,方法上加了静态static 成为类锁后会顺序执行。
我们来小小总结一下:
-
类锁对该类的所有对象都能起作用,而对象锁不能。
-
多线程访问某类中synchronized修饰的静态和非静态方法时是可以异步执行的。