java中synchronized Lock(本地同步)锁的8种情况

目录
  • lock1
  • lock2
  • lock3
  • lock4
  • lock5
  • lock6
  • lock7
  • lock8

Lock(本地同步)锁的8种情况总结与说明:

* 题目:
* 1.标准访问,请问是先打印邮件还是短信 Email
* 2.email方法新增暂停4秒钟,请问是先打印邮件还是短信 Email
* 3.新增普通的hello方法,请问先打印邮件还是hello hello
* 4.两部手机,请问先打印邮件还是短信 SMS
* 5.两个静态同步方法,1部手机,请问先打印邮件还是短信 Email
* 6.两个静态同步方法,2部手机,请问先打印邮件还是短信 Email
* 7.一个普通同步方法,一个静态同步方法,1部手机,请问先打印邮件还是短信 SMS
* 8.一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信 SMS
*
* lock1、2
* 一个对象里面如果有多个synchronized方法,某一时刻内,只要一个线程去调用其中的一个synchronized方法,
* 其他的线程都只能等待,换句话说,某一时刻内,只能有唯一一个线程去访问这些synchronized方法,
* 锁的是当前对象的this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
*
* lock3、4
* 加个普通的方法后和同步锁无关
* 换成两个对象后,不是同一把锁了,情况立刻变化
*
* lock5、6
* 都换成静态同步方法后,情况又变化(静态锁的是Class类对象)
* 若是普通同步方法,new this,具体的一部一部手机,所有的普通同步方法用的都是同一把锁----示例对象本身
* 若是静态同步方法,static class,唯一的一个模板
* synchronized是实现同步的基础:Java中的每一个对象都可以作为锁
* 具体表现为一下3种形式。
* 对于普通同步方法,锁是当前实例对象。它等同于 对于同步方法块,锁是synchronized括号里的配置的对象。
* 对于静态同步方法,锁是当前类的Class类元信息
*
* lock7、8
* 当一个线程试图访问同步代码块时它首先必须得到锁,退出或抛出异常时必须释放锁
*
* 所有的同步方法用的都是同一把锁----实例对象本身,就是new出来的具体实例对象本身
* 也就是说如果一个实例对象的普通同步方法获取锁后,该实例对象的其他普通同步方法必须等待获取锁的方法释放锁后才能获得锁
* 可是别的实例对象的普通同步方法因为跟该实例对象的普通同步方法用到是不同锁,所以不用等待该实例对象已获取锁的普通
* 同步方法释放锁就可以获取它们自己的锁
*
* 所有的静态同步方法用的也是同一把锁----类对象本身,就是我们说过的唯一模板Class
* 具体实例对象this和唯一模板Class,这两把锁是两个不同的对象,所有静态同步方法与普通同步方法之间是不会有竞态条件的,
* 但是一旦一个静态同方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁。

lock1、2、3一个实例对象

lock4、5、6、7、8两个实例对象

lock1

1.标准访问,请问是先打印邮件还是短信?答案:Email

sendEmail()与sendSms()都是普通同步方法,都使用synchronized锁

这里按方法调用顺序,依次执行,当前synchronized锁住的是同一个实例对象

package day02_lam;

import java.util.concurrent.TimeUnit;

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

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

}

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信     Email
*/
public class Lock8{
	public static void main(String[] args) throws InterruptedException{
        Phone phone=new Phone();
        //线程A发送Email
        new Thread(()->{
                try{
                    phone.sendEmail();
                }catch(InterruptedExceptione){
                    e.printStackTrace();
                }
            },"A").start();

        Thread.sleep(300);

        //线程B发送短信
        newThread(()->{
            phone.sendSms();
        },"B").start();
    }
}

lock2

2.email方法新增暂停4秒钟,请问是先打印邮件还是短信? 答案:Email

lock2是lock1的变形,其原理与lock1一致,synchronized锁住的是同一个对象,必须等到第一个方法把锁释放后,第二个方法才能够获得锁

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
	public synchronized void sendEmail()throwsInterruptedException{
        //睡眠4秒种
		TimeUnit.SECONDS.sleep(4);
		System.out.println("------------sendEmail");
	}

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

}

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*/
public class Lock8{
    public static void main(String[] args)throws InterruptedException{
        //资源类
        Phone phone=new Phone();

        //线程A sendEmail
        newThread(()->{
            try{
                phone.sendEmail();
            }catch(InterruptedExceptione){
                e.printStackTrace();
            }
        },"A").start();

		//这里保证线程A能够执行完
   	 	Thread.sleep(300);

        //线程B sendSms
        newThread(()->{
            phone.sendSms();
        },"B").start();

    }
}

结果:等待4秒中后出现sendEmail与sendSMS同时输出

lock3

3.新增普通的hello方法,请问先打印邮件还是hello? 答案:hello

只有添加synchronized关键字的方法才会被synchronized锁控制

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
	public synchronized void sendEmail()throws InterruptedException{
		TimeUnit.SECONDS.sleep(4);
		System.out.println("------------sendEmail");
	}

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

	public void hello(){//未加synchronized
		System.out.println("hello");
	}
}

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hello    hello
*/
public  class Lock8{
    public static void main(String[] args)throws InterruptedException{
        Phone phone=new Phone();

        //线程A调用sendEmail
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch(InterruptedExceptione){
                e.printStackTrace();
            }
        },"A").start();

   		Thread.sleep(300);

       	//线程B调用普通方法hello
        new Thread(()->{
            //phone.sendSms();
            phone.hello();
        },"B").start();

    }
}

结果:hello先输出,4s后sendEmail再输出

lock4

4.两部手机,请问先打印邮件还是短信 ? 答案:SMS

不同实例对象,synchronized锁住的是对应的调用对象

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
	public synchronized void sendEmail()throws InterruptedException{
        //睡眠4秒种
		TimeUnit.SECONDS.sleep(4);
		System.out.println("------------sendEmail");
	}

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

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

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hellohello
*4.两部手机,请问先打印邮件还是短信 SMS
*/
public class Lock8{
public static void main(String[] args)throws InterruptedException{
		Phone phone=new Phone();
		Phone phone2=new Phone();

		//sychronized锁定是当前对象对应的this,phone与phone2分别锁的是自己的this

    	//线程A使用实例phone调用sendEmail
		newThread(()->{
			try{
                //sendEmail方法中包含睡眠4秒种
				phone.sendEmail();
			}catch(InterruptedExceptione){
				e.printStackTrace();
			}
		},"A").start();

		Thread.sleep(300);

    	//线程B使用实例phone2调用sendSms
		newThread(()->{
			phone2.sendSms();
			//phone.hello();
		},"B").start();

	}
}

结果:sendSMS先输出,4s后sendEmail再输出

lock5

5.两个静态同步方法,1部手机,请问先打印邮件还是短信? 答案:Email

synchronized锁静态方法,实际是锁住的类元信息,因为静态方法是随类元信息的加载而保存到jvm的静态区,是所有实例创建的模板

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
	public static synchronized void sendEmail()throws InterruptedException{
		TimeUnit.SECONDS.sleep(4);
		System.out.println("------------sendEmail");
	}

	public static synchronized void sendSms(){

		System.out.println("------------sendSMS");
	}

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

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hellohello
*4.两部手机,请问先打印邮件还是短信SMS
*5.两个静态同步方法,1部手机,请问先打印邮件还是短信 Email
*/
public class Lock8{
public  static void main(String[] args)throws InterruptedException{
	Phone phone=new Phone();

	new Thread(()->{
		try{
			phone.sendEmail();
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	},"A").start();

	Thread.sleep(300);

	newThread(()->{
		phone.sendSms();
	},"B").start();

	}
}

结果:4秒种后,sendEmail率先输出,sendSMS紧随其后

lock6

6.两个静态同步方法,2部手机,请问先打印邮件还是短信? 答案:Email

与lock5的运行结果一致,当前synchronized锁住的是类元信息

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
    public static synchronized void sendEmail() throws InterruptedException{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("------------sendEmail");
    }

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

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

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hellohello
*4.两部手机,请问先打印邮件还是短信SMS
*5.两个静态同步方法,1部手机,请问先打印邮件还是短信Email
*6.两个静态同步方法,2部手机,请问先打印邮件还是短信Email
*/
public class Lock8{
    publicstaticvoidmain(String[]args)throwsInterruptedException{
        Phone phone=new Phone();
        Phone phone2=new Phone();

        new Thread(()->{
            try{
            	phone.sendEmail();
            }catch(InterruptedException e){
           	 e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(300);
        new Thread(()->{
            //phone.sendSms();
            phone2.sendSms();
            //phone.hello();
        },"B").start();

    }
}

结果:与lock5的运行结果一致,sendEmail与sendSMS都是4s后进行输出,synchronized也是锁住的类元信息

lock7

7.一个普通同步方法,一个静态同步方法,1部手机,请问先打印Email还是SMS? 答案:SMS

原理:普通同步方法,synchronized锁住的是当前实例对象,当前实例对象存在于jvm的堆内存区

静态同步方法,synchronized锁住的是当前类的类元信息,存在于jvm元空间的静态区中

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
    //静态同步方法
	public static synchronized void sendEmail()throws InterruptedException{
		TimeUnit.SECONDS.sleep(4);
		System.out.println("------------sendEmail");
	}

    //普通同步方法
	public synchronized void sendSms(){//无static

		System.out.println("------------sendSMS");
	}

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

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hellohello
*4.两部手机,请问先打印邮件还是短信SMS
*5.两个静态同步方法,1部手机,请问先打印邮件还是短信Email
*6.两个静态同步方法,2部手机,请问先打印邮件还是短信Email
*7.一个普通同步方法,一个静态同步方法,1部手机,请问先打印邮件还是短信 SMS
*/
public class Lock8{
	public static void main(String[] args) throws InterruptedException{
		Phonephone=newPhone();
		Phonephone2=newPhone();

		newThread(()->{
			try{
				phone.sendEmail();
			}catch(InterruptedExceptione){
				e.printStackTrace();
			}
		},"A").start();

		Thread.sleep(300);

		newThread(()->{
			phone.sendSms();
			//phone2.sendSms();
			//phone.hello();
		},"B").start();

	}
}

结果:sendSMS先输出,4s后sendEmail再输出

lock8

8.一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信? 答案:SMS

原理:与lock7一致

package day02_lam;

import java.util.concurrent.TimeUnit;

class Phone{
	public static synchronized void sendEmail()throwsInterruptedException{
		TimeUnit.SECONDS.sleep(3);
		System.out.println("------------sendEmail");
	}

	public synchronized void sendSms(){

		System.out.println("------------sendSMS");
	}

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

/**
*题目:
*1.标准访问,请问是先打印邮件还是短信Email
*2.email方法新增暂停4秒钟,请问是先打印邮件还是短信Email
*3.新增普通的hello方法,请问先打印邮件还是hellohello
*4.两部手机,请问先打印邮件还是短信SMS
*5.两个静态同步方法,1部手机,请问先打印邮件还是短信Email
*6.两个静态同步方法,2部手机,请问先打印邮件还是短信Email
*7.一个普通同步方法,一个静态同步方法,1部手机,请问先打印邮件还是短信SMS
*8.一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信SMS
*/
public class Lock8{
	publicstaticvoidmain(String[]args)throwsInterruptedException{
		Phone phone=new Phone();
		Phone phone2=new Phone();

		new Thread(()->{
			try{
				phone.sendEmail();
			}catch(InterruptedExceptione){
				e.printStackTrace();
			}
		},"A").start();

		Thread.sleep(300);

		new Thread(()->{
			//phone.sendSms();
			phone2.sendSms();
			//phone.hello();
		},"B").start();

	}
}

结果:运行结果与lock7一致,sendSMS先输出,4s后sendEmail再输出

到此这篇关于java中synchronized Lock(本地同步)锁的8种情况的文章就介绍到这了,更多相关 synchronized Lock锁内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    synchronized 和 Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同步方式.显式锁是JDK1.5引入的,这两种锁有什么异同呢?是仅仅增加了一种选择还是另有其因?本文为您一探究竟. // synchronized关键字用法示例 public synchronized void add(int t){// 同步方法 this.v += t; } public stati

  • 详解Java中的锁Lock和synchronized

    一.Lock接口 1.Lock接口和synchronized内置锁 a)synchronized:Java提供的内置锁机制,Java中的每个对象都可以用作一个实现同步的锁(内置锁或者监视器Monitor),线程在进入同步代码块之前需要或者这把锁,在退出同步代码块会释放锁.而synchronized这种内置锁实际上是互斥的,即没把锁最多只能由一个线程持有. b)Lock接口:Lock接口提供了与synchronized相似的同步功能,和synchronized(隐式的获取和释放锁,主要体现在线程进

  • java中synchronized Lock(本地同步)锁的8种情况

    目录 lock1 lock2 lock3 lock4 lock5 lock6 lock7 lock8 Lock(本地同步)锁的8种情况总结与说明: * 题目: * 1.标准访问,请问是先打印邮件还是短信 Email * 2.email方法新增暂停4秒钟,请问是先打印邮件还是短信 Email * 3.新增普通的hello方法,请问先打印邮件还是hello hello * 4.两部手机,请问先打印邮件还是短信 SMS * 5.两个静态同步方法,1部手机,请问先打印邮件还是短信 Email * 6.两

  • 一文带你搞懂Java中Synchronized和Lock的原理与使用

    目录 1.Synchronized与Lock对比 2.Synchronized与Lock原理 2.1 Synchronized原理 2.2 Lock原理 3.Synchronized与Lock使用 Synchronized Lock 4.相关问题 1.Synchronized与Lock对比 实现方式:Synchronized是Java语言内置的关键字,而Lock是一个Java接口. 锁的获取和释放:Synchronized是隐式获取和释放锁,由Java虚拟机自动完成:而Lock需要显式地调用lo

  • Java中synchronized关键字引出的多种锁 问题

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这些锁分别的优缺点. 一 synchronized机制 synchronized关键字是JAVA中常用的同步功能,提供了简单易用的锁功能. synchronized有三种用法,分别为: 用在普通方法上,能够锁住当前对象.用在静态方法上,能够锁住类用在代码块上,锁住的是synchronized()里的对

  • 透彻理解Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别

    本文讲述了Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别.分享给大家供大家参考,具体如下: Synchronized和Static Synchronized区别 通过分析这两个用法的分析,我们可以理解java中锁的概念.一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁).实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是

  • Java中synchronized关键字修饰方法同步的用法详解

    Java的最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问. 每一个用synchronized关键字声明的方法都是临界区.在Java中,同一个对象的临界区,在同一时间只有一个允许被访问. 静态方法则有不同的行为.用synchronized关键字声明的静态方法,同时只能够被一个执行线程访问,但是其他线程可以访问这个对象的非静态的synchronized方法.必须非常谨慎这一点,因为两个线程可以同时访问一个对象的两个不同的synchronized方法,即其中一个是静态s

  • java中synchronized(同步代码块和同步方法)详解及区别

     java中synchronized(同步代码块和同步方法)详解及区别 问题的由来: 看到这样一个面试题: //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized (obj){} } synchronized用于解决同步问题,当有多条线程同时访问共享数据时,如果进行同步,就会发生错误,Java提供的解决方案是:只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他

  • Java中synchronized锁升级的过程

    目录 简介 CAS markWord Synchronized的锁升级 偏向锁 轻量级锁 重量级锁 总结 简介 在多线程中解决线程安全的问题时常用到Synchronized,现在的synchronized相对于早期的synchronized做出了优化,从以前的加锁就是重量级锁优化成了有一个锁升级的过程(偏向锁->轻量级锁->重量级锁). CAS cas的全称是compare and swap,从名称上可以看出它是先比较再进行设置,它是一种在多线程环境下实现同步功能的机制. 下面这段代码是在Re

  • 教你Java中的Lock锁底层AQS到底是如何实现的

    目录 前言 加锁 释放锁 总结 前言 相信大家对Java中的Lock锁应该不会陌生,比如ReentrantLock,锁主要是用来解决解决多线程运行访问共享资源时的线程安全问题.那你是不是很好奇,这些Lock锁api是如何实现的呢?本文就是来探讨一下这些Lock锁底层的AQS(AbstractQueuedSynchronizer)到底是如何实现的. 本文是基于ReentrantLock来讲解,ReentrantLock加锁只是对AQS的api的调用,底层的锁的状态(state)和其他线程等待(No

  • Java中CountDownLatch进行多线程同步详解及实例代码

    Java中CountDownLatch进行多线程同步详解 CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantLock.ReadWriteLock锁实现同步. 3.信号量Semaphore实现同步. 其中,synchronized关键字和Lock锁解决的是多个线程对同一资源的并发访问问题.信号量Semaphore解决的是多副本资源的共享访问问题. 今天

  • Java中synchronized实现原理详解

    记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予它一个名字"同步",也成为了我们解决多线程情况的百试不爽的良药.但是,随着我们学习的进行我们知道synchronized是一个重量级锁,相对于Lock,它会显得那么笨重,以至于我们认为它不是那么的高效而慢慢摒弃它. 诚然,随着Javs SE 1.6对synchronized进行的各种优化后,synchronized并不会显得那么

随机推荐