精华内容
下载资源
问答
  • 一、线程安全、 二、锁机制 ( 类锁 | 对象锁 )、 三、锁分类 ( 轻量级锁 | 重量级锁 )、





    一、线程安全



    多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量是线程安全的 ; 这里的数据是指主内存中的共享变量以及各个线程中的变量副本 , 保证这些变量一致 , 就是线程安全 ;

    线程安全 就是保证 线程操作的 原子性 , 可见性 , 有序性 ;

    volatile 关键字可以保证 可见性 有序性 ;

    synchronized 关键字可以保证 原子性 ;





    二、锁机制 ( 类锁 | 对象锁 )



    synchronized 是 Java 提供的一种锁机制 ;

    在普通方法上加锁 , 相当于对 this 进行加锁 ; 下面两个类的 fun 方法的线程锁是等效的 ;

    public class Student {
        private synchronized void fun() {
        }
    }
    
    public class Student {
        private void fun() {
            synchronized(this){
            }
        }
    }
    

    加锁的代码块 , 在同一个时间 , 只能由 1 1 1 个线程访问 ;


    对象锁 : synchronized() 代码块中 , 括号中的参数是 作用范围 ; synchronized(this) 表示作用范围只针对当前对象 , 如果 创建了多个对象 , 这几个对象中的锁都是 不同的锁 , 相互之间没有任何关系 ;

    Student s1 = new Student();
    Student s2 = new Student();
    

    只有当多个线程 , 访问同一个对象时 , 锁才有意义 ;

    如 :
    线程 A 访问 s1 对象的 fun 方法 , 线程 B 访问 s2 对象的 fun 方法 , 两个方法之间 没有互斥效果 ;
    线程 A 访问 s1 对象的 fun 方法 , 线程 B 也想访问 s1 对象的 fun 方法 , 此时必须 等待线程 A 访问完毕 , 释放锁之后 , 才能由线程 B 访问 s1 ;


    类锁 : 如果加锁的对象是静态方法 , 那么相当于在 Student.class 类上进行加锁 ; Student.class 对象全局只有 1 1 1 个 , 调用所有对象的 fun 方法 , 都是互斥的 ;

    public class Student {
        private synchronized static void fun() {
        }
    }
    

    等价于

    public class Student {
        private static void fun() {
            synchronized(Student.class){
            }
        }
    }
    




    三、锁分类 ( 轻量级锁 | 重量级锁 )



    如果线程 A 获得锁之后 , 执行线程内容 , 其它线程等待解锁时有两种情况 :

    • 轻量级锁 : 又称为 自旋锁 , 线程 盲等待 或 自旋等待 , 即 while 循环 , 没有进入阻塞状态 , 没有进入等待队列中排队 ; ( 轻量级 )
    • 重量级锁 : 线程进入 等待队列 , 排队等待线程 A 执行完毕 ; 在该队列的线程 , 需要 等待 OS 进行线程调度 , 一旦涉及到操作系统 , 量级就变重 , 效率变低 ; ( 重量级 )

    轻量级锁弊端 : 轻量级锁 不一定 比重量级锁 更好 ; 轻量级锁 等待过程中 , 高速执行循环代码 , 如果循环的时间很短 , 时间效率上很高 ; 但是一旦执行时间很长 , 比如连续执行十几秒甚至几分钟 , 浪费了大量的 CPU 资源 ;


    使用场景 :

    • 轻量级锁 : 轻量级锁只适合 线程少 , 等待时间短的 应用场景 , 如果线程很多 , 等待时间过长 , 会造成 CPU 大量浪费 ;
    • 重量级锁 : 重量级锁等待过程中 , 线程处于阻塞状态 , 效率可能低一些 , 但是不会造成资源浪费 , 如果 线程很多 , 或 等待时间很长 , 适合使用重量级锁 ;
    展开全文
  • 自旋可以使线程在没有取得的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得,则继续执行。若线程依然不能获得,才会被挂起。 使用...
     
    1、自旋锁
    自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行。若线程依然不能获得锁,才会被挂起。
    使用自旋锁后,线程被挂起的几率相对减少,线程执行的连贯性相对加强。因此,对于那些锁竞争不是很激烈,锁占用时间很短的并发线程,具有一定的积极意义,但对于锁竞争激烈,单线程锁占用很长时间的并发程序,自旋锁在自旋等待后,往往毅然无法获得对应的锁,不仅仅白白浪费了CPU时间,最终还是免不了被挂起的操作 ,反而浪费了系统的资源。
    在JDK1.6中,Java虚拟机提供-XX:+UseSpinning参数来开启自旋锁,使用-XX:PreBlockSpin参数来设置自旋锁等待的次数。
    在JDK1.7开始,自旋锁的参数被取消,虚拟机不再支持由用户配置自旋锁,自旋锁总是会执行,自旋锁次数也由虚拟机自动调整。

    可能引起的问题:
    1.过多占据CPU时间:如果锁的当前持有者长时间不释放该锁,那么等待者将长时间的占据cpu时间片,导致CPU资源的浪费,因此可以设定一个时间,当锁持有者超过这个时间不释放锁时,等待者会放弃CPU时间片阻塞;
    2.死锁问题:试想一下,有一个线程连续两次试图获得自旋锁(比如在递归程序中),第一次这个线程获得了该锁&#x
    展开全文
  • 对象锁和类锁的区别

    千次阅读 2020-04-12 16:47:25
    对象锁和类锁的区别synchronized 关键字对象锁1、锁住 this 对象2、 锁住实体里的非静态变量3、直接锁非静态方法对象锁代码测试类锁1、锁住 xxx.class2、锁住类中的静态变量3、直接在静态方法上加 synchronized类锁...


    生活中不存在绝对的自由,绝对的自由通常对应的无序和混沌,只有在道德、法律、伦理的约束下的相对自由,才能使人感受到自由。
    而在多线程编程中,锁是至关重要的,锁就是道德,就是法律约束,没有锁的多线程环境将会是混乱的,所有线程都在争夺资源,最后的结果就是导致系统崩溃,而有了锁之后,多线程环境才能稳定高效的工作。

    synchronized 关键字

    synchronized 是我们所说的重量级锁,所说的重量级是相对于那些自旋锁(AQS)而言的,比如可重入锁ReentrantLock。很多人谈 synchronized 色变,说它性能差、太重,貌似言之凿凿。放在多年前确实如此,但是 Java 1.7、1.8 已经对 synchronized 做了很大优化,其性能和那些轻量级锁几乎没有差距。
    所以,我们再程序中其实可以放心的使用它,即使没有用过,也肯定在一些源码里见过,比如 Netty 中就有很多地方用到了它。
    下面开始进入今天的主题,类锁和实例锁。看名字就已经很明显了,类锁就是所在类上的锁,实例就是锁在类实例上的锁。

    对象锁

    类声明后,我们可以 new 出来很多的实例对象。这时候,每个实例在 JVM 中都有自己的引用地址和堆内存空间,这时候,我们就认为这些实例都是独立的个体,很显然,在实例上加的锁和其他的实例就没有关系,互不影响了。

    通常我们使用实例锁的方式有下面三种:

    1、锁住 this 对象

    this 指的是当前对象实例本身,所以,所有使用 synchronized(this)方式的方法都共享同一把锁。
    在这里插入图片描述

    2、 锁住实体里的非静态变量

    非静态变量是实例自身变量,不会与其他实例共享,所以锁住实体内声明的非静态变量可以实现对象锁。锁住同一个变量的方法块共享同一把锁。
    在这里插入图片描述

    3、直接锁非静态方法

    最简单、最直观的一种方式,直接加在方法返回类型前。
    在这里插入图片描述

    使用对象锁的情况,只有使用同一实例的线程才会受锁的影响,多个实例调用同一方法也不会受影响。

    对象锁代码测试

    下面来做个测试,开启 5 个线程,每个线程都 new 一个新的实例来分别调用上面三种方式的方法,方法完成的动作就是输出线程名称,然后休眠 10 秒钟。

    public class ObjectLock {
    
    	private Object lock = new Object();
    	
    	/**     
    	* 锁住非静态变量     
    	* @throws InterruptedException     
    	*/    
    	public void lockObjectField() throws InterruptedException {        
    		synchronized (lock) {            
    			System.out.println(Thread.currentThread().getName());            
    			Thread.sleep(10*1000);        
    		}    
    	}    
    
    	/**     
    	* 锁住 this 对象 this 就是当前对象实例     
    	* @throws InterruptedException     
    	*/    
    	public void lockThis() throws InterruptedException {        
    		synchronized (this) {            
    			System.out.println(Thread.currentThread().getName());            
    			Thread.sleep(10*1000);        
    		}    
    	}   
    	 /**     
    	 * 直接锁住非静态方法     
    	 * @throws InterruptedException     
    	 */    
    	public synchronized void methodLock() throws InterruptedException {   
    		System.out.println(Thread.currentThread().getName());        
    	 	Thread.sleep(10*1000);    
    	}   
      
    	public static void main(String[] args) {        
    		for (int i = 0; i < 5; i++) {            
    	  		Thread worker = new Thread(new ObjectLockWorker());            
    	  		worker.setName("kite-" + i);            
    	  		worker.start();        
    	  	}    
    	}    
    
    	public static class ObjectLockWorker implements Runnable {        
    		@Override        
    	  	public void run() {           
    			try {               
    	    		ObjectLock objectLock = new ObjectLock();                
    	    		// 方式 1                
    	    		objectLock.lockObjectField();                
    	    		// 方式 2                
    	    		//objectLock.lockThis();                
    	    		// 方式 3                
    	    		//objectLock.methodLock();            
    	    	} catch (Exception e) {                
    	    		e.printStackTrace();           
    	    	}        
    	    }    
    	}
    
    }
    
    

    我们预测的结果就是每个线程都会立刻输出线程名称,然后各自休眠 10 秒。

    分别调用方式1、2、3,效果都是一样的,我们看到输出结果和我们预测的是一样的,5 个线程都立即输出线程名,然后等待 10 秒,整个程序退出。

    类锁

    类锁是加载类上的,而类信息是存在 JVM 方法区的,并且整个 JVM 只有一份,方法区又是所有线程共享的,所以类锁是所有线程共享的。

    使用类锁的方式有如下方式:

    1、锁住 xxx.class

    对当前类的 .class 属性加锁,可以实现类锁。
    在这里插入图片描述

    2、锁住类中的静态变量

    因为静态变量和类信息一样也是存在方法区的并且整个 JVM 只有一份,所以加在静态变量上可以达到类锁的目的。
    在这里插入图片描述

    3、直接在静态方法上加 synchronized

    因为静态方法同样也是存在方法区的并且整个 JVM 只有一份,所以加在静态方法上可以达到类锁的目的。
    在这里插入图片描述

    类锁是所有线程共享的锁,所以同一时刻,只能有一个线程使用加了锁的方法或方法体,不管是不是同一个实例。

    类锁代码测试

    下面同样来做个测试,开启 5 个线程,除了调用静态方法的方式,其他两种方式中每个线程都 new 一个新的实例来分别调用,方法内完成的动作就是输出线程名称,然后休眠 10 秒钟。

    public class ClassLock { 
    
    	private static Object lock = new Object();
    
    	/**
    	 * 锁住静态变量
    	 *
    	 * @throws InterruptedException
    	 */
    	public void lockStaticObjectField() throws InterruptedException {
    		synchronized (lock) {
    			System.out.println(Thread.currentThread().getName());
    			Thread.sleep(10 * 1000);
    		}
    	}
    	
    	/**
    	 * 锁住静态方法
    	 *
    	 * @throws InterruptedException
    	 */
    	public static synchronized void methodLock() throws InterruptedException {
    		System.out.println(Thread.currentThread().getName());
    	  	Thread.sleep(10 * 1000);
    	}
    	
    	/**
    	 * 锁住 xxx.class
    	 *
    	 * @throws InterruptedException
    	 */
    	public void lockClass() throws InterruptedException {
    		synchronized (ClassLock.class) {
    	    	System.out.println(Thread.currentThread().getName());
    	    	Thread.sleep(10 * 1000);
    	  	}
    	}
    	
    	public static void main(String[] args) {
    		for (int i = 0; i < 5; i++) {
    	   		Thread worker = new Thread(new ClassLockWorker());
    	    		worker.setName("kite-" + i);
    	    		worker.start();
    	 	 }
    	}
    	
    	public static class ClassLockWorker implements Runnable {
    		@Override
    	  	public void run() {
    	    	try {
    	      		ClassLock classLock = new ClassLock();
    	      		// 方式 1
    				// classLock.lockStaticObjectField();
    				// 方式 2
    				// ClassLock.methodLock();
    				// 方式 3
    				// classLock.lockClass();
    	    	} catch (Exception e) {
    	      		e.printStackTrace();
    	    	}
    	  	}
    	}
    
    
    }
    
    

    我们预测的结果就是刚开始只有1个线程抢到锁,然后输出线程名,之后等待 10 秒中,之后是下一个抢到锁的线程,输出线程名,然后等待 10 秒。直到最后一个抢到锁的线程,整个过程历时大约 50 秒。

    分别调用方式1、2、3,观察执行结果,和我们预测的是一致的。

    总结

    • 使用对象锁的情况,只有使用同一实例的线程才会受锁的影响,多个实例调用同一方法也不会受影响。

    • 类锁是所有线程共享的锁,所以同一时刻,只能有一个线程使用加了锁的方法或方法体,不管是不是同一个实例。

    展开全文
  • 自旋可以使线程在没有取得的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得,则继续执行。若线程依然不能获得,才会被挂起。 使用...
    参考:http://blog.csdn.net/a314773862/article/details/54095819
    


    自旋锁

    自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行。若线程依然不能获得锁,才会被挂起。

    使用自旋锁后,线程被挂起的几率相对减少,线程执行的连贯性相对加强。因此,对于那些锁竞争不是很激烈,锁占用时间很短的并发线程,具有一定的积极意义,但对于锁竞争激烈,单线程锁占用很长时间的并发程序,自旋锁在自旋等待后,往往毅然无法获得对应的锁,不仅仅白白浪费了CPU时间,最终还是免不了被挂起的操作 ,反而浪费了系统的资源。

    可能引起的问题:
    1.过多占据CPU时间:如果锁的当前持有者长时间不释放该锁,那么等待者将长时间的占据cpu时间片,导致CPU资源的浪费,因此可以设定一个时间,当锁持有者超过这个时间不释放锁时,等待者会放弃CPU时间片阻塞;
    2.死锁问题:试想一下,有一个线程连续两次试图获得自旋锁(比如在递归程序中),第一次这个线程获得了该锁,当第二次试图加锁的时候,检测到锁已被占用(其实是被自己占用),那么这时,线程会一直等待自己释放该锁,而不能继续执行,这样就引起了死锁。因此递归程序使用自旋锁应该遵循以下原则:递归程序决不能在持有自旋锁时调用它自己,也决不能在递归调用时试图获得相同的自旋锁。


    阻塞锁

    让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。。
    JAVA中,能够进入\退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait()\notify()


    可重入锁

    避免死锁

    可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。
    在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁


    悲观锁和乐观锁

    悲观锁(Pessimistic Lock), 顾名思义就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。共享锁、排它锁、独占锁是悲观锁的一种实现

    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号或时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。使用CAS来保证,保证这个操作的原子性

    乐观锁不是数据库自己实现的

    悲观锁是数据库自己实现的


    两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于 写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。


    轮循锁和定时锁

    由tryLock实现,与无条件获取锁模式相比,它们具有更完善的错误恢复机制。可避免死锁的发生:
    boolean tryLock():仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。


    显示锁和内置锁

    显示锁用Lock来定义、内置锁用syschronized。
    内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
    内置锁是互斥锁


    读写锁

    Lock接口以及对象,使用它,很优雅的控制了竞争资源的安全访问,但是这种锁不区分读写,称这种锁为普通锁。为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制,如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。
    Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock,详细的API可以查看JavaAPI文档。
    ReentrantReadWriteLock 和 ReentrantLock 不是继承关系,但都是基于 AbstractQueuedSynchronizer 来实现。
    lock方法 是基于CAS 来实现的
    ReadWriteLock中暴露了两个Lock对象:

    在读写锁的加锁策略中,允许多个读操作同时进行,但每次只允许一个写操作。读写锁是一种性能优化的策略。

    RentrantReadWriteLock在构造时也可以选择是一个非公平的锁(默认)还是公平的锁。


    对象锁和类锁

    java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。
    类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的.
    synchronized只是一个内置锁的加锁机制,当某个方法加上synchronized关键字后,就表明要获得该内置锁才能执行,并不能阻止其他线程访问不需要获得该内置锁的方法。

    调用对象wait()方法时,会释放持有的对象锁,以便于调用notify方法使用。notify()调用之后,会等到notify所在的线程执行完之后再释放锁


    锁粗化

    锁粗化的概念应该比较好理解,就是将多次连接在一起的加锁、解锁操作合并为一次,将多个连续的锁扩展成一个范围更大的锁


    互斥锁

    互斥锁, 指的是一次最多只能有一个线程持有的锁。如Java的Lock


    无锁状态-》偏向锁-》轻量级锁-》重量级锁

    锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)。JDK 1.6中默认是开启偏向锁和轻量级锁的,
    锁膨胀:从轻量锁膨胀到重量级锁是在轻量级锁解锁过程发生的。
    重量级锁:Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么Synchronized效率低的原因。因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为“重量级锁”。
    轻量级锁:“轻量级”是相对于使用操作系统互斥量来实现的传统锁而言的。但是,首先需要强调一点的是,轻量级锁并不是用来代替重量级锁的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用产生的性能消耗。在解释轻量级锁的执行过程之前,先明白一点,轻量级锁所适应的场景是线程交替执行同步块的情况,如果存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁。
    偏向锁: 引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令(由于一旦出现多线程竞争的情况就必须撤销偏向锁,所以偏向锁的撤销操作的性能损耗必须小于节省下来的CAS原子指令的性能消耗)。上面说过,轻量级锁是为了在线程交替执行同步块时提高性能,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。

    无锁状态:在代码进入同步块的时候,如果同步对象锁状态为无锁状态。


    锁消除

    锁消除即删除不必要的加锁操作。根据代码逃逸技术,如果判断到一段代码中,堆上的数据不会逃逸出当前线程,那么可以认为这段代码是线程安全的,不必要加锁。



    展开全文
  • HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Object Header)、实例数据(Instance Data)对齐填充(Padding)。 对象头(Object Header)  JVM的对象头包括二/三部分信息:1、Mark ...
  • 是偏向于一个给定的线程,锁定解锁可以在不使用原子操作的情况下由该线程执行。当的偏差被撤销时,它将恢复到正常状态下面描述的锁定方案。注意:Hotspot不会在JVM启动的最初几秒(目前是4秒)内启用偏向锁定...
  • 这可能导致两个或多个线程同时访问相同的字段或对象。 同步是使执行中的所有并发线程保持同步的过程。同步可避免由于共享内存视图不一致而导致的内存一致性错误。当方法声明为synchronized时 ; 该线程持有监视器...
  • 方法锁和对象锁说的是一个东西,即只有方法锁或对象锁和类锁两种锁java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁称为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或...
  • java中每个对象都可作为锁,锁有四种级别,按照量级从轻到重分为:无锁、偏向锁、轻量级锁、重量级锁。并且锁只能升级不能降级。 在讲这三个锁之前,我先给大家讲清楚自旋和对象头的概念。 自旋 现在假设有这么一...
  • synchronized中重量级锁、偏向锁轻量级锁区别

    千次阅读 多人点赞 2019-08-06 20:29:36
    我们先介绍重量级锁,然后介绍优化后的轻量级锁和偏向锁。 0.对象头以及Mark Word 1重量级锁 重量级的synchronized有三个用法: 普通同步方法,锁的是当前实例对象。 静态同步方法,锁的是当前类的clas...
  • 偏向锁:当一个线程访问对象时,它会偏向这个...这时对象已经存在竞争了,此时检查原来持有该对象锁的线程是否依然存活,如果挂了,则可以将对象变为无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,而且还.
  • 1、对象监视器锁(重量级锁)、轻量级锁、偏向锁的含义 2、它们之间的区别 3、每一种锁的使用场景什么。 我们跟着一下几个问题一步一步深入了解: 什么是对象监视器锁 为什么它叫重量级锁   我们知道在...
  • 三、的优化 1、升级 2、粗化 3、消除 一、Synchronized使用场景 Synchronized是一个同步关键字,在某些多线程场景下,如果不进行同步会导致数据不安全,而Synchronized关键字就是用于代码同步。什么...
  • 前言 Java 对象头(Java Object Header)
  • 很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,Java SE1.6中为了减少获得锁释放锁带来的性能消耗而引入的偏向锁轻量级锁,以及锁的存储结构...
  • jdk1.6之后,因为线程状态间的切换低效,所以对synchronized实现同步功能进行了优化,引入偏向锁,轻量级锁,自旋锁重量级锁等概念,来提高synchronized实现同步锁的效率。 synchronized获取不到锁之后,不会立即...
  • 偏向所锁,轻量级锁都是乐观锁,重量级锁是悲观锁。 一个对象刚开始实例化的时候,没有任何线程来访问它的时候。它是可偏向的,意味着,它现在认为只可能有一个线程来访问它,所以当第一个 线程来访问它的时候,它会...
  • Java对象锁的理解

    万次阅读 热门讨论 2018-07-16 14:57:27
    以前理解Java的锁机制认为:锁的类型分为‘类锁’,’方法锁‘,’对象锁‘。 1.类锁(synchronize(静态对象)):类的所有对象都要竞争锁。 2.方法锁(在方法前加synchronize): 同一对象同一方法需要竞争锁。 3....
  • 对象锁共有四种状态:无锁、偏向锁、轻量级锁、重量级锁,锁竞争程度依次加重。 对象锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。 自旋是一种获取锁的策略,存在于获取轻量级锁的过程中...
  • 下面的语句用来查询哪些对象:  select object_name,machine,s.sid,s.serial#  from v$locked_object l,dba_objects o ,v$session s  where l.object_id = o.object_id and l.session_id=s.sid; ...
  • JVM系列之:对象状态同步

    万次阅读 2020-07-24 09:14:07
    文章目录简介java对象头java中锁状态的变化偏向锁biased locking轻量级锁thin lock重量级锁三种锁状态的不同 简介 锁同步是java多线程编程中非常常见的使用场景。为了锁定多线程共享的对象,Java需要提供一定的...
  • 偏向锁,轻量级锁与重量级锁区别与膨胀

    万次阅读 多人点赞 2017-03-19 20:44:01
    一直被这三个锁的膨胀问题所困扰,不知道到底实在什么时候会有偏向锁升级到轻量级锁,什么时候由轻量级锁升级到重量级锁。找到好久,也没有找到简洁明了的答案。  综合多个方面的描述综合自己的理解,特地记录下来...
  • Java synchronized之类锁/对象锁

    千次阅读 2017-11-03 18:24:15
    对象锁是基于对堆内存内对象的头部加锁信息; 类锁是基于对类对应的 java.lang.Class对象加所信息; 特别的, synchronized(this) 是对this所对应的对象加锁。需要特别注意的事是, 根据JMM的规范, synchronized 块...
  • 偏向锁轻量级锁

    千次阅读 2017-01-05 17:57:50
    当一个线程访问同步块并获取的时候,会在对象栈帧中的琐记录里存储偏向的线程ID,以后线程在进入同一个同步块时,不需要进行CAS操作,来加锁解锁。只需简单的测试对象头的Mark Word里是否存储这指向当前...
  • 重量级锁:一个同步的A线程对应着一个monitor对象(该对象和对象是异议对应的关系,用来记录等待获得锁对象的锁标记的线程已经获得锁标记的线程),堆空间对象对象头上会记录一个,这个锁信息指向monitor对象...
  • 区别 偏向锁:当一个线程访问对象时,它会偏向这个...这时对象已经存在竞争了,此时检查原来持有该对象锁的线程是否依然存活,如果挂了,则可以将对象变为无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,而
  • synchronized原理,偏向锁,轻量级锁,重量级锁,锁升级
  • 文章目录1 synchronized的优化1.1 CAS操作1.1.1 CAS带来的ABA问题1.1.2 自旋会浪费大量的处理器资源1.1.3 公平性1.2 Java对象头1.2.1 偏向1.2.1 偏向的获取1.2.1 偏向的撤销1.2.3 偏向的获得撤销流程 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 198,957
精华内容 79,582
关键字:

对象锁和类锁的区别