显式锁与隐式锁的区别和同步代码块的理解 -- 转载

本文详细比较了Java中的隐式锁(Synchronized)和显式锁(ReentrantLock),包括它们的构成、使用方法、中断能力、公平性以及如何控制多个条件。理解Synchronized的自动管理与Lock的灵活性,有助于提升多线程编程效率。

引言

在多线程的程序中,JAVA为了具体的控制每个线程的,所以有了锁机制,锁又被分为显式锁和隐式锁.

隐式锁(Synchronized)

隐式锁中又分为同步代码块和同步方法,但是都是基于Synchronized关键字来实现的,因为他只需要是使用管关键字就可以,不用显示加锁和解锁的过程,所以称之为隐式锁,具体的实现可以参考下面的代码:

同步代码块

public void method(){
        synchronized(this){
            //要锁住的代码
            //一次只能有一个线程来指向这段代码
        }
    }

1.上面的代码是同步代码块,就是在代码块前面加上Synchroized关键字,并在后面的小括号内传入锁对象,这里的this是指定了当前的这个对象作为锁,注意任何对象都是可以作为锁来使用的.

2.这个是排队执行,一个线程进入代码块时,就会把这个锁对象的状态变成上锁状态,其他的线程发现是上锁状态时,就会在外面等待,直到这个线程将锁住的代码块执行完毕之后,将锁对象的状态变为解锁,其他的线程才会一起抢,谁抢到就重复上面的操作,知道满足某个条件,程序结束.

补充: 同步代码块理解

1、同步代码块的理解

public void test01(){
	Synchronized(this){
		//共享代码
	}
}

上文中的this指代进入此代码块的线程对象,如果线程Thread1首先进到同步代码块后,会将同步代码块中的代码全部锁住,当线程Thread2也进到此处,线程Thread2只能处于等待状态,需要等到线程Thread1执行完同步代码后才能够进入。
  这样的话,该方式比同步方法public synchronized void fun(){}更优越,因为,后者锁住了方法中所有的代码。

  
2、类同步的理解

public void test02(){
	Synchronized(xx.class){
		//共享代码
	}
}

同步的是类对象,在不同线程中,只要是这个类的对象都会同步等待。

转载连接:https://blog.csdn.net/weixin_43334389/article/details/108790563

同步方法

public synchronized void method(){
        //方法体
    }

同步方法就是将Synchroized关键字方放在方法的返回值前面,这里的锁就是也就是this,谁调用它,谁就是他的锁.
原理跟同步代码块一样,但是这里的锁因为是this,如果在一个线程对象里有多个方法,那么第一个线程执行时给这个this上了锁,那么其他方法都是不能执行的.只有等一个方法执行完了之后,改变锁的状态,其他的才可以执行.

显式锁(Lock)

显式锁的概念是相对于隐式锁的,因为显式锁在使用的时候程序员可以控制上锁和解锁,所以称之为显式.显式锁是一个借口,不能直接使用,所以要使用它的实现类来进行操作,他一共有三个实现类,分别是ReentrantLock.ReentrantReadWriteLock.ReadLock和ReentrantReadWritLock.WritLock.因为现在只学了第一种,所以只来解释第一种.

public class Demo03 implements Runnable {
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        l.lock();
        try{
            //要锁住的代码
        }catch(Exception e){
            //异常的处理逻辑
        }finally{
            l.unlock();
        }
    }
}

我们首先要在线程类里面定义一个锁对象,
然后通过他的lock()方法来上锁,锁住的东西就是直到调用它unlock()方法开锁之前的所有代码,显式锁如果上锁,一定要记得在最后开锁,建议写在finally代码块里面.还要注意只有上了锁才能开锁,不上锁开锁系统会报异常.

两者的区别

Synchronized是内部实现的,不需要人为控制,jvm会在内部自动改变锁的状态,而Lock是需要上锁和解锁的.,而且只上锁不解锁或者只解锁不上锁都是不可以的
Synchronized是针对代码块来上锁的,就是如果代码运行到同步代码块或者同步方法外面,锁就会自动解开.
而Lock是针对于一个对象,不论你有多少的代码,只要上锁之后没有用unlock解锁,这个东西都是被锁住的,而且还会有异常,程序员还要对异常进行处理.这个虽然麻烦,但是他也提供了一个便利,就是开锁和解锁不必在同一个代码块里面,就增加了可操作性
因为隐式锁是jvm在检测和处理,所以在一般情况下,还是隐式锁比较好用.

原文链接:https://blog.csdn.net/weixin_45573037/article/details/106157406

显式锁与隐式锁的区别

转载:https://blog.csdn.net/weixin_48043585/article/details/109156214

解决的方法 格式 描述
同步代码块(关键字) synchronized(锁对象){} 隐式锁,多个线程的锁对象必须唯一
同步方法(修饰符) synchronized 返回类型 方法名(){} 隐式锁,谁调用该方法谁就是锁对象
显示锁 ReentrantLock类的lock()/unlock()方法 显式锁,有程序员决定在那开启/关闭锁

一、构成不同

Sync 和 Lock 的出身(原始的构成)不同:

Sync:Java中的关键字,是由JVM来维护的。是JVM层面的锁。

Lock:是JDK5以后才出现的具体的类。使用 Lock 是调用对应的API。是API层面的锁。

Sync 底层是通过 monitorenter 进行加锁(底层是通过 monitor 对象来完成的,其中的wait/notify等方法也是依赖于 monitor 对象的。只有在同步代码块或者同步方法中才可以调用wait/notify等方法。因为只有在同步代码块或者是同步方法中,JVM才会调用 monitory 对象);通过 monitorexit 来退出锁。

而 Lock 是通过调用对应的API方法来获取锁和释放锁。

二、使用方法不同

Sync是隐式锁;Lock是显示锁。

所谓的显示和隐式就是在使用的时候,使用者要不要手动写代码去获取锁和释放锁。

在使用sync关键字的时候,程序能够自动获取锁和释放锁。那是因为当sync代码块执行完成之后,系统会自动的让程序释放占用的锁。Sync是由系统维护的,如果非逻辑问题的话,是不会出现死锁的。
在使用lock的时候,我们使用者需要手动的获取和释放锁。如果没有释放锁,就有可能导致出现死锁的现象。手动获取锁方法:lock();释放锁:unlock()。

三、等待是否可中断

Sync是不可中断的。除非抛出异常或者正常运行完成。

Lock是可以中断的。中断方式:

调用设置超时方法tryLock(long timeout ,timeUnit unit)
调用lockInterruptibly()放到代码块中,然后调用interrupt()方法可以中断

四、加锁的时候是否公平

Sync:非公平锁。

Lock:两者都可以。默认是非公平锁,在其构造方法的时候可以传入Boolean值(true:公平锁;false:非公平锁)

五、锁绑定多个条件来condition

Sync:没有。要么随机唤醒一个线程;要么是唤醒所有等待的线程。

Lock:用来实现分组唤醒需要唤醒的线程,可以精确的唤醒,而不是像sync那样,不能精确唤醒线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值