现象一
多个线程使用一把锁,也就是调用同一个对象,谁先调用谁先执行
被 synchronized 修饰的方法、锁的对象是方法的调用者
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程使用同一个对象(同一把锁)
Phone phone = new Phone();
new Thread(()->{phone.sendMessage();}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{phone.call();}).start();
}
}
class Phone {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
public synchronized void sendMessage(){
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
现象二
多个线程使用同一把锁,某个锁方法里有阻塞,依旧是谁先调用谁先执行
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程使用同一个对象(同一把锁)
Phone phone = new Phone();
new Thread(()->{
phone.sendMessage();
}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone.call();
}).start();
}
}
class Phone {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
public synchronized void sendMessage(){
// 添加阻塞
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
现象三
多个线程中既有 有锁方法 也有无锁方法 会 随机执行
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程使用同一个对象(同一把锁)
Phone phone = new Phone();
new Thread(()->{
phone.sendMessage();
}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone.call();
}).start();
}
}
class Phone {
// synchronized 锁的对象是方法的调用者!
public synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
// 这里是无锁方法
public void call(){
System.out.println("打电话");
}
}
现象四
多个线程调用多个对象,多个线程使用多把锁, 会随机执行
Synchronized 锁的是方法调用者,两个线程调用两个不同的对象,所以互不干扰
package com.it.lock8;
import java.util.concurrent.TimeUnit;
/**
* @author shkstart
* @create 2020-06-18 9:21
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程分别使用两把锁
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone1.sendMessage();
}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone2.call();
}).start();
}
}
class Phone {
// synchronized 锁的对象是方法的调用者!
public synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
现象五
Class锁,static和synchronized 修饰的方法
多个线程使用一个对象(一把锁)但是被 static修饰 ,锁的是class文,全局只有一个 会 顺序执行
被 synchronized 和 static 同时修饰的方法,锁的对象是类的 class 对象,是唯一的一把锁。线程之间是顺序执行。
锁Class和锁对象的区别:
1、Class 锁 ,类模版,只有一个;
2、对象锁 , 通过类模板可以new 多个对象
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程使用同一把锁
Phone phone = new Phone();
new Thread(()->{
phone.sendMessage();
}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone.call();
}).start();
}
}
class Phone {
// synchronized 锁的对象是方法的调用者!
// static 和 synchronized 同时修饰锁的是class
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
现象六
Class锁,static和synchronized 修饰的方法
多个线程使用多个对象(多把锁)但是被 static修饰 ,锁的是class文,全局只有一个 会 顺序执行
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程分别使用两把锁
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone1.sendMessage();
}).start();
TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone2.call();
}).start();
}
}
// class 是唯一的class对象
class Phone {
// synchronized 锁的对象是方法的调用者!
// static 和 synchronized 同时修饰锁的是class
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
现象七
一个静态同步方法 一个普通同步方法
多个线程去操作同一个对象 会先执行普通同步方法
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程分别使用两把锁
Phone phone = new Phone();
new Thread(()->{
phone.sendMessage();
}).start();
// TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone.call();
}).start();
}
}
// class 是唯一的class对象
class Phone {
// synchronized 锁的对象是方法的调用者!
// static 和 synchronized 同时修饰锁的是class
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
现象八
两个静态同步方法,两个对象
顺序执行
public class Test {
public static void main(String[] args) throws InterruptedException {
// 两个线程分别使用两把锁
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone1.sendMessage();
}).start();
// TimeUnit.SECONDS.sleep(3); // 中途睡眠
new Thread(()->{
phone2.call();
}).start();
}
}
// class 是唯一的class对象
class Phone {
// synchronized 锁的对象是方法的调用者!
// static 和 synchronized 同时修饰锁的是class
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
总结
-
被 synchronized 修饰的方法,锁的对象是方法的调用者(实例对象)
-
被 static synchronized 修饰的方法,锁的对象就是 Class模板对象,这个则全局唯一
synchronized修饰的 多个线程调用单个对象(一把锁) 顺序执行
synchronized 修饰的 多个线程调用多个对象(多把锁) 随机执行
因为synchronized修饰 锁的是方法调用者(对象),
所以单个对象的时候谁先调用谁就先拿到锁先执行
多个对象的时候根据CPU调度,随机执行
static synchronized 修饰的 多个线程调用单个对象 顺序执行
static synchronized 修饰的 多个线程调用多个对象 顺序执行
因为 static synchronized 修饰 锁的是class 全局唯一
所以单个单个对象或多个对象调用的时候都是顺序执行