8锁问题
8锁就是8个锁的问题,直接探究出到底锁的是谁:
借用一个Phone类,里面有打电话和发短信两个方法,答案就是先发短信还是先打电话:
那么是先发短信还是先打电话呢?
/** * @Description: * @Package: com.nerr.lock8 * @ClassName: demo01 * @Author: nerr * @Date: 2021/6/22 * @Version: 1.0 */ public class Demo01 { public static void main(String[] args) { Phone phone = new Phone(); new Thread(()->{ phone.sms(); },"a").start(); new Thread(()->{ phone.call(); },"b").start(); } } class Phone{ public synchronized void sms(){ System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }
答案是:先发短信
解释:synchronized 锁的是方法的调用者,也就是对象锁。两个方法持有的是同一把锁,因此谁先拿到锁谁先执行
2.
那么是先发短信还是先打电话呢?发短信先沉睡3秒钟
import java.util.concurrent.TimeUnit;
public class Demo02 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
Phone2 phone1 = new Phone2();
new Thread(()->{
phone.sms();
},"a").start();
new Thread(()->{
phone1.call();
},"b").start();
}
}
class Phone2{
public synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
答案是先打电话
3.
import java.util.concurrent.TimeUnit;
/*
一个同步方法,一个普通方法,一个对象调用
让发短信沉睡3秒
*/
public class Demo03 {
public static void main(String[] args) {
Phone3 phone = new Phone3();
new Thread(()->{
phone.sms();
},"a").start();
new Thread(()->{
phone.call();
},"b").start();
new Thread(()->{
phone.game();
},"c").start();
}
}
class Phone3{
public synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
public void game(){
System.out.println("打游戏");
}
}
答案是:打游戏=>发短信=>打电话
描述:让发短信先沉睡3秒
/*
两个同步方法,一个对象调用
*/
import java.util.concurrent.TimeUnit;
public class Demo04 {
public static void main(String[] args) {
Phone4 phone = new Phone4();
new Thread(() -> {
phone.sms();
}, "a").start();
new Thread(() -> {
phone.call();
}, "b").start();
}
}
class Phone4{
public synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
答案是:先发短信
原因:synchronized 锁的是方法的调用者,也就是对象锁。两个方法持有的是同一把锁,因此谁先拿到锁谁先执行
描述:发短信沉睡3秒钟
/*
两个静态同步方法,一个对象调用
*/
import java.util.concurrent.TimeUnit;
public class Demo05 {
public static void main(String[] args) {
Phone5 phone = new Phone5();
new Thread(() -> {
Phone5.sms();
}, "a").start();
new Thread(() -> {
Phone5.call();
}, "b").start();
}
}
class Phone5{
public static synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
答案:先发短信
/*
两个静态同步方法,两个对象调用
*/
import java.util.concurrent.TimeUnit;
public class Demo06 {
public static void main(String[] args) {
Phone6 phone = new Phone6();
Phone6 phone6 = new Phone6();
new Thread(() -> {
Phone6.sms();
}, "a").start();
new Thread(() -> {
Phone6.call();
}, "b").start();
}
}
class Phone6{
public static synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
static方法类一加载就执行,synchronized 锁的是Class对象即类所,两个方法持有两把把锁,而打电话不沉睡3秒
import java.util.concurrent.TimeUnit;
public class Demo07 {
public static void main(String[] args) {
Phone7 phone = new Phone7();
new Thread(() -> {
Phone7.sms();
}, "a").start();
new Thread(() -> {
phone.call();
}, "b").start();
}
}
class Phone7{
public static synchronized void sms(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
答案:先打电话
原因:静态同步方法和普通同步方法分别是类锁和对象锁,相当于两把锁,普通同步方法不要等待。
import java.util.concurrent.TimeUnit; public class Demo08 { public static void main(String[] args) { Phone8 phone = new Phone8(); Phone8 phone8 = new Phone8(); new Thread(() -> { Phone8.sms(); }, "a").start(); new Thread(() -> { phone8.call(); }, "b").start(); } } class Phone8{ public static synchronized void sms(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }
答案:先打电话
总结:
普通带锁方法:锁对象,同一对象下的才按顺序执行,如果是同一个类下的不同对象则不受影响。
普通不带锁方法:不受任何影响。
静态带锁方法:锁类,同一个类下的所有对象的所有带锁方法都得按顺序执行。