首页 > 试题广场 >

说说synchronize的用法及原理

[问答题]
synchronized可以修饰静态方法、普通方法、代码块。 能够保证同一个时刻只有一个线程执行该段代码,保证线程安全。 在执行完或者出现异常时自动释放锁。 synchronized作用在代码块时,它的底层是通过monitorenter、monitorexit指令来实现的。
发表于 2022-04-26 16:07:43 回复(1)
一、用法:1. 静态方法上,则锁是当前类的Class对象。 2. 作用在普通方法上,则锁是当前的实例(this)。 3. 作用在代码块上,则需要在关键字后面的小括号里,显式指定一个对象作为锁对象。 能够保证同一个时刻只有一个线程执行该段代码,保证线程安全。 在执行完或者出现异常时自动释放锁。 二、原理:底层是采用Java对象头来存储锁信息的,并且还支持锁升级。在JVM里的实现都是 基于进入和退出Monitor对象来实现方法同步和代码块同步,
发表于 2022-05-01 18:09:03 回复(1)
用法:synchronize主要用于实现多线程对共享数据的互斥同步,其作用位置不同,加锁对象也就不同。作用于类或类中的静态方法时,加锁对象为类对象,作用于非静态方法时,加锁的对象类对象实例,作用位置为一个方法中的代码块时则为该类对象的部分代码加锁。 原理:在jvm的锁对象头中有一个markword用来记录锁对象的状态,分别有无锁,偏向锁,轻量级锁,重量级锁四种状态。最开始锁处于无锁状态,当第一个线程请求该锁并获得以后该锁的状态便变为偏向锁状态,并且线程对象会记录该锁表明当前获取到了该锁,在偏向锁状态中并不会有任何阻塞同步操作,甚至cas操作也不需要。直到有其它线程开始请求锁时,锁就会不再进入偏向锁状态。在后续中当一个线程请求到锁会先使用CAS操作来避免互斥同步带来的性能消耗直到CAS操作失败。这一时段内锁处于轻量级锁状态。失败后严格按照互斥同步处理,此时锁就处于重量级锁状态。
发表于 2022-05-11 15:03:14 回复(0)
用法:synchronized可以修饰普通方法,静态方法和同步代码块。 偏向锁原理:当线程第一次访问同步块并获取锁时,检测Mark Word是否为可偏向状态,即是否为偏向锁1,锁标识位为01为偏向锁,若为可偏向状态,则判断Mark word中的线程ID是否为当前线程ID,如果是,执行同步代码块,否则通过CAS操作将Mark Word的线程ID替换为当前线程ID,执行同步代码块。持有偏向锁的线程以后每次进入这个锁相关的同步块时,jvm都可以不再进行任何同步操作只需要判断id是否一致。偏向锁的效率高。 轻量级锁原理:1.判断当前对象是否处于无锁状态(hashcode、 0、01) , 如果是,则JVM首先将在当前线程的栈帧中建立-个名为锁记录(Lock Record)的空间,将对象的Mark Word复制到栈帧中的Lock Record中,将Lock Reocrd中的owner指向当前对象。2. JVM利用CAS操作尝试将对象的Mark Word存储指向Lock Record的指针,如果成功表示竞争到锁,则将锁标志位变成00变为轻量级锁,执行同步操作。3.如果失败则判断当前对象的Mark Word是否指向当前线程的栈帧,如果是则表示当前线程已经持有当前对象的锁,则直接执行同步代码块;否则只能说明该锁对象已经被其他线程抢占了,这时轻量级锁需要膨胀为重量级锁,锁标志位变成10,后面等待的线程将会进入阻塞状态。 重量级锁原理:当锁住一个线程时,会先去monitor对象中判断owner变量是否为空,为空就将owner存储当前线程以及通过cas将mark word存储指向monitor的指针指向当前monitor,然后当再有线程来时发现owner不为空将当前线程阻塞,并且放入entrylist集合中以链表的形式存储起来,当monitor中的owner置为null会释放掉该锁,然后entrylist里的线程被唤醒后,采用CAS去抢锁(这是不公平的,属于抢占式调度)重新竞争cpu的使用权。
编辑于 2023-05-16 14:06:37 回复(0)
用法:1、静态方法、普通方法、代码块;目的:保证同一个时刻只有一个进程执行这部分代码,保证线程安全。原理:使用Java对象头来存储锁信息,支持锁升级;1.6之后所分为无锁、偏向锁、轻量级锁、重量级锁。锁能升级不能降级;采用CAS + mark word 实现,mark word来存储锁信息。
发表于 2023-03-28 10:50:28 回复(0)
synchronized关键字可以用在三个地方,用在普通方法上,锁的对象是当前实例,用在静态方法上,锁的对象是class对象,用在代码块上,需要在后面指定一个显式对象作为锁.三种地方,对应不同锁的颗粒度,能保证被它修饰的方法或代码块,同一时间只有一个线程执行,并且保证资源的同步,可见性和原子性. 线程和进程都是CPU调度的,线程的执行,表示jvm里需要有这个线程的信息,而线程私有的空间为 虚拟机栈,本地方法栈,程序计数器,线程共有的空间有堆(类的信息)和方法区() 原理:synchronized底层是使用对象头来存储锁的信息,并且支持锁升级,对象头包括三部分分别是:Mark word(存储对象的hashcode及锁信息--锁的标注和锁的状态) /Class Metadata Address(存储对象类型的指针元空间数据?)/Array length存储数组对象的长度(不是数组则没有) java版本为了降低获取锁和释放锁的损耗,引入,无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态,随线程竞争情况升级,锁状态逐步升级.synchronized引入偏向锁(偏向于某个线程,当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程再进入和退出同步块时就不需要做加锁和解锁操作了,只需要简单地测试一下Mark Word里是否存储着自己的线程ID即可) 和 轻量级锁,就是加锁时JVM会在当前线程栈帧中创建用于存储锁的空间,并将Mark Word复制到锁记录中,然后线程尝试以CAS方式将Mark Word替换为指向锁记录的指针,如果成功,这当前线程获得锁,如果失败这表示其他线程竞争锁,此时,当前线程只会通过自璇来尝试获取锁. 锁升级过程
发表于 2023-02-10 10:26:14 回复(0)
1、synchronized加在三个不同的位置,对应三种不同的使用方式,这三种方式的区别是锁对象不同:
(1.)加在普通方法上,则锁是当前的实例(this)。
(2.)加在静态方法上,锁是当前类的Class对象。
(3.)加在代码块上,则需要在关键字后面的小括号里,显式指定一个对象作为锁对象。
2. synchronized是比较早期的API,在设计之初没有考虑到超时机制、非阻塞形式,以及多个条件变量。
3、Lock支持的功能包括:支持响应中断、支持超时机制、支持以非阻塞的方式获取锁、支持多个条件变量(阻塞队列)。
JDK的开发团队在1.5引入了Lock接口,并通过Lock支持了上述的功能。Lock支持的功能包括:支持响应中断、支持超时机制、支持以非阻塞的方式获取锁、支持多个条件变量(阻塞队列)。
synchronized采用“CAS+Mark Word”实现,为了性能的考虑,并通过锁升级机制降低锁的开销。
在并发环境中,synchronized会随着多线程竞争的加剧,按照如下步骤逐步升级:无锁、偏向锁、轻量级锁、重量级锁。
Lock则采用“CAS+volatile”实现,其实现的核心是AQS。
AQS是线程同步器,是一个线程同步的基础框架,它基于模板方法模式。
在具体的Lock实例中,锁的实现是通过继承AQS来实现的,并且可以根据锁的使用场景,派生出公平锁、不公平锁、读锁、写锁等具体的实现。
编辑于 2023-02-02 19:05:07 回复(0)
作用在静态方法上,表示锁定这个类,作用在普通方法上,表示锁定这个对象,作用在代码块时,在后面的小括号中需要显示指定需要对象
发表于 2022-09-18 15:47:08 回复(0)
syn锁可以用在方法上,静态方法上 变量上 保证同时只有一个线程能进入代码块。执行完或者异常自动释放锁。 原理是对象头 对象头有3, markword 存储对象的hashcode和锁信息,metadata address 对象类型指针 arraylenth对象数组长度
编辑于 2024-04-02 16:12:39 回复(0)
1. 静态方法上,则锁是当前类的Class对象。 2. 作用在普通方法上,则锁是当前的实例对象。 3. 作用在代码块上,则需要在关键字后面的小括号里,显式指定一个对象作为锁对象。 能够保证同一个时刻只有一个线程执行该段代码,保证线程安全。 在执行完或者出现异常时自动释放锁。 二、原理:底层是采用Java对象头(MarkWord 1是偏向 0是非偏向)来存储锁信息的,并且还支持锁升级。在JVM里的实现都是 基于进入和退出Monitor对象来实现方法同步和代码块同步, 是非公平锁
编辑于 2024-04-01 17:49:18 回复(0)
答:synchronized可以修饰静态方法、普通方法、代码块。能够保证同一个时刻只有一个线程执行该段代码,保证线程安全。在执行完或者出现异常时自动释放锁。synchronized作用在代码块时,底层通过monitor enter以及monitor exit指令实现。
编辑于 2024-03-27 21:57:12 回复(0)
synchronized关键字 可用来修饰静态方法(锁定类对象)、普通方法(锁定this对象)、代码块(this对象) 能够保证同一时刻只有一个线程执行该段代码 ,保证线程安全 。 在执行完或发生异常时会自动释放锁 。 原理:通过对象头来存储锁信息的,基于进入Monitor或退出来实现方法的同步和代码块的同步
编辑于 2024-02-28 21:47:39 回复(0)
1. synchronize 有三种用户:普通方法(当前对象实例)、静态方法(当前类class对象)、代码块(指定小括号锁对象) 2. 原理:对象头存储锁信息,JVM提供两种指令实现方法同步和代码块同步 monitor enter/exit
编辑于 2024-02-22 17:34:43 回复(0)
用法: 同步方法: 在方法定义中使用synchronized关键字,可以确保整个方法在同一时间只能被一个线程执行。 public synchronized void synchronizedMethod() { // 同步的代码块 } 同步代码块: 使用synchronized关键字创建同步代码块,将需要同步的代码包裹在这个块内。通常,你需要提供一个锁对象(也称为监视器对象)来作为同步的依据。 public void someMethod() { // 非同步代码 synchronized (lockObject) { // 需要同步的代码 } // 非同步代码 } 原理: synchronized关键字的原理基于Java对象的内置锁机制(也称为监视器锁)。每个Java对象都有一个相关联的锁,当一个线程进入一个synchronized方法或代码块时,它会尝试获取这个对象的锁。如果锁已经被其他线程占用,线程将被阻塞,直到锁被释放。 以下是synchronized关键字的工作原理: 当一个线程尝试进入一个synchronized方法或代码块时,它会尝试获取对象的锁。 如果锁没有被其他线程占用,当前线程将获得锁,并执行关键部分。 如果锁已经被其他线程占用,当前线程将被阻塞,直到锁被释放。 一旦线程完成了关键部分的执行,它将释放锁,允许其他等待的线程竞争锁。 这个机制确保了在同一时间只有一个线程能够执行关键部分,从而保护了共享资源免受并发访问的干扰。 需要注意的是,synchronized方法或代码块的锁是与对象实例关联的,而不是与方法或代码块本身关联的。这意味着对于不同的对象实例,它们的synchronized方法或代码块可以并行执行,因为它们使用了不同的锁。
发表于 2023-09-25 11:02:35 回复(0)
先说用法: synchronized锁是互斥锁,能够保证同一时刻只有一个线程持有锁,可以修饰静态方法、普通方法和代码块; 修饰静态方法时,锁是当前类的Class对象;修饰普通方法时,锁是当前实例;修饰代码块时,需要在关键字后面的括号里显示的指定一个对象锁; 原理:源码在jvm中,底层是通过Java对象头存储锁信息,jdk1.6之后还支持锁升级;在jvm里的实现是基于monitor对象来实现方法同步和代码块同步的;monitor对象中有三个变量owner(存储当前持有锁线程的id)、entrylist(阻塞队列)、waitset(等待队列)
发表于 2023-08-23 10:52:54 回复(0)
synchronized可以修饰静态方法(锁加在类对象上),普通方法(锁加在类对象实例(this上)),代码块(关键字后面声明锁对象)。synchronized可以保证线程执行某段代码时其他线程不能执行,保证了线程安全。底层是采用java对象头来存储锁信息,基于monitor对象实习代码块和方法的同步
发表于 2023-08-11 15:47:36 回复(0)
1.用法:可以修饰静态方法、普通方法和代码块。通过升级锁的方式,减小锁的开销。根据线程竞争资源的激烈程度从无锁、偏向锁、轻量级锁、重量级锁升级。 2.底层原理:是通过对象头实现的。对象头中中的MarkWord是升级锁的重要参数,因为锁标志和锁状态都在这个参数中。 3.锁的升级 ·假如有两个线程,刚开始没有线程对资源进行操作,此时处于无锁状态 ·线程1以更新修改的方式改变MarkDown的值,此时只有一个线程,加偏向锁成功 ·线程2也以CAS的方式尝试改变MarkDown的值,此时出现了竞争,加偏向锁失败。线程2就会撤销发起偏向锁的流程,同步块从偏向线程1的状态进入公平竞争状态 ·二者共同竞争,同时以CAS方式修改MarkDown,尝试加轻量级锁,由于存在竞争,只有一个线程加锁成功,另一个线程会自旋加锁 ·如果线程1很快执行完,执行权就落在线程2.如果线程1执行了很久,线程2自旋加锁到了一定程度,就放弃加锁,此时,线程2将锁修改为重量级锁,之后进入阻塞状态。而线程1重复加锁或解锁时都会失败,它就释放锁并唤醒等待的线程2。
发表于 2023-07-13 11:27:58 回复(0)
synchronized是Java提供的用于表示线程执行同步的关键字,可以修饰static方法、普通方法、代码块,线程访问修饰的部分前,需要获取对应的对象锁,是悲观锁、非公平锁、可重入锁、不可中断锁。 修饰静态方法,线程访问前需要获取Class对象锁。 修饰普通方法,线程访问需要获取类实例对象锁。 修饰代码块,线程访问前需要获取指定对象的对象锁。 synchronized基于CAS+对象头实现,对象头中存储了锁的状态和锁的拥有者,jvm会根据竞争情况进行锁升级,修改对象头的信息,会由无锁->偏向锁->轻量级锁->重量级锁。
发表于 2023-07-03 15:59:22 回复(0)
synchronized可以修饰静态方法,普通方法,代码块。保证这一时刻只有一个线程执行该关键字修饰的代码,保证线程安全。执行结束或异常时释放锁。
发表于 2023-03-11 11:01:59 回复(0)
synchronized一般用于修饰方法、代码块。能保证线程安全问题,在执行完成后自动释放锁。synchronized是一个可重入锁,不可中断锁,隐式锁。它是一个基于对象的锁,锁的信息存储在对象的对象头中,在1.6之前synchronized是一个重量级锁,每次线程切换都需要上下文切换,从内核态到用户态的切换,花费大量时间,影响性能。1.6之后加入了锁升级,从无锁到偏向锁到轻量级锁再到重量级锁的升级,且不可逆。synchronized的可重入原理是基于计数器的实现,每次只能一个线程获取到锁,但每次该线程再次获取到锁的时候,计数器加一,释放锁计数器减一。
发表于 2023-03-10 10:26:42 回复(0)