【JUC —— 04 8锁问题】

"8锁问题"是一个经典的多线程问题,主要测试对Java中synchronized关键字的理解,以及线程同步和锁机制的掌握。这个问题通常涉及到8种不同的情况,通过不同的锁和调用顺序,来观察哪个线程会先执行。以下是对8种情况的详细解释和代码示例。

题目描述

假设有两个方法sendEmailsendSMS,以及一个普通方法hello,我们会在不同的条件下调用它们,观察它们的执行顺序。

情况1:两个方法都加锁,两个线程分别调用这两个方法

结果sendEmail先执行,然后sendSMS执行。因为两个方法都加了synchronized,且是同一个对象锁。

class Phone {
    public synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS() {
        System.out.println("sendSMS");
    }

    public void hello() {
        System.out.println("hello");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone.sendSMS();
        }, "Thread2").start();
    }
}

情况2:一个方法加锁,另一个方法不加锁,两个线程分别调用这两个方法

结果sendSMSsendEmail的执行顺序不确定。因为sendSMS没有锁,不受sendEmail锁的影响。

class Phone {
    public synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone.sendSMS();
        }, "Thread2").start();
    }
}

情况3:两个方法都加锁,且是静态锁,两个线程分别调用这两个方法

结果sendEmail先执行,然后sendSMS执行。静态同步方法使用的是类锁(Phone.class),两个线程互斥。

class Phone {
    public static synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public static synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(() -> {
            Phone.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            Phone.sendSMS();
        }, "Thread2").start();
    }
}

情况4:一个静态同步方法,一个非静态同步方法,两个线程分别调用这两个方法

结果sendEmailsendSMS的执行顺序不确定。一个是类锁,一个是对象锁,不互斥。

class Phone {
    public static synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public static synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone1.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone2.sendSMS();
        }, "Thread2").start();
    }
}

情况5:两个静态同步方法,两个对象,两个线程分别调用这两个方法

结果sendEmail先执行,然后sendSMS执行。静态同步方法使用的是类锁,不管多少个对象,锁都是同一个。

class Phone {
    public static synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public static synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone1.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone2.sendSMS();
        }, "Thread2").start();
    }
}

情况6:两个非静态同步方法,两个对象,两个线程分别调用这两个方法

结果sendEmailsendSMS的执行顺序不确定。两个对象有各自的锁,不互斥。

class Phone {
    public synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone1.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone2.sendSMS();
        }, "Thread2").start();
    }
}

情况7:一个非静态同步方法,一个非同步方法,两个对象,两个线程分别调用这两个方法

结果sendSMSsendEmail的执行顺序不确定。sendSMS没有锁,不受sendEmail锁的影响。

class Phone {
    public synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone1.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone2.sendSMS();
        }, "Thread2").start();
    }
}

情况8:一个静态同步方法,一个非同步方法,两个对象,两个线程分别调用这两个方法

结果sendSMSsendEmail的执行顺序不确定。一个是类锁,一个是对象锁,不互斥。

class Phone {
    public static synchronized void sendEmail() {
        System.out.println("sendEmail");
    }

    public void sendSMS() {
        System.out.println("sendSMS");
    }
}

public class EightLocks {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone1.sendEmail();
        }, "Thread1").start();

        new Thread(() -> {
            phone2.sendSMS();
        }, "Thread2").start();
    }
}

总结

synchronized锁的是方法的调用者(拥有者)

通过"8锁问题"可以深入理解Java中的锁机制和synchronized关键字的使用。不同的锁(类锁对象锁),不同的调用顺序和条件(静态方法和非静态方法),会导致不同的执行结果。通过这些案例,可以更好地理解并发编程中的锁机制。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值