模拟一个手机类(资源),现在有发邮件和发短信两个功能。两个线程取操作这个资源类,是先发邮件还是先发短信。
一锁:标准访问代码 ,先打印邮件还是短信
class Phone{
public synchronized void sendEmail(){
System.out.println(Thread.currentThread().getName() + ":sendEmail");
}
public synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
结果:

解析:
两个线程各自去找各自需要的资源,他们需要的资源都使用着同一把锁,所以只有一个线程可以先获得资源的执行权,另一个线程则需要等待上一个线程执行完毕才能执行。
二锁:邮件方法暂定4秒,先打印邮件还是短信
class Phone{
public synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
结果

解析:
和一锁道理相同,因为使用的是一把锁,而且邮件方法使用的sleep方法不会释放锁,所以线程B需要等线程A唤醒后执行完毕后才能执行。
三锁:新增一个普通方法hello,先打印邮件还是hello
class Phone{
public synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void hello(){
System.out.println(Thread.currentThread().getName() + ":hello");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone.hello();
},"B").start();
}
}
结果

解析:
hello方法没有加同步,所以不受锁的影响。
四锁:两个手机对象,A线程打印第一部手机的邮件,B打印第二部手机的短信,先打印邮件还是短信
class Phone{
public synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}
结果:

解析:
两个对象使用的是两把锁,所以互不干扰。
五锁:两个静态同步方法,同一个手机对象,先打印邮件还是短信
class Phone{
public static synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
结果:

解析:
和第二锁相同,只是加了静态方法,但是还是共用一把锁
六锁:两个静态同步方法,两个手机对象,A线程打印第一部手机的邮件,B打印第二部手机的短信,先打印邮件还是短信
class Phone{
public static synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}

解析:
静态方法的作用范围是从这个类的唯一的字节码文件开始的,相当于把这个手机模板中的方法上锁了,这样以来不管多少对象都是用的这个模板中上了锁的方法。
七锁:一个普通同步方法,一个静态同步方法,一个手机对象,先打印邮件还是短信
class Phone{
public static synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
结果:

解析:
静态方法锁的是字节码中的方法,这是一把锁,然后普通同步方法用的当前类的对象做锁,这又是一把锁,两个方法没有使用同一把锁,所以互不影响。两个锁分别是(class的锁,this的锁)
八锁:一个普通同步方法,一个静态同步方法,两个手机对象,先打印邮件还是短信
class Phone{
public static synchronized void sendEmail(){
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + ":sendEmail");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName() + ":sendSMS");
}
}
public class EightLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
Thread.sleep(100);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}
结果:

解析:
和七锁相同,虽然变成两个对象了,但是还是两把不同的锁,互不影响。