精华内容
下载资源
问答
  • 对象级别锁 vs 类级别锁我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或...

    前言

    对于多线程(并发)和Spring Boot这两块在同步进行学习中,在看到使用synchronized关键字使操作同步时,看到和C#中不一样的东西,所以这里呢,就深入学习了下,若有错误之处,还望指正。

    对象级别锁 vs 类级别锁

    我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或锁定对象,如果有另外一个线程也在执行该同步方法,那么该线程将被阻塞,直到线程释放该监视器或锁定对象。我们在类中已定义的方法或块上使用synchronized关键字,同时synchronized关键字不能与类定义中的变量或属性一起使用。

    对象级别锁

    所谓的对象级别锁,也就是针对非静态方法执行同步块锁定,那么同步块中的监视器或锁定对象则是基于对象实例,有如下三种形式

    classTest {public synchronized voidLockMethod() {

    }

    }

    或者

    classTest {public voidLockMethod() {synchronized(this)

    {

    }

    }

    }

    或者

    classTest {private final Object lock = newObject();public voidLockMethod() {synchronized(lock) {

    }

    }

    }

    类级别锁

    若在同步方法中存在静态数据,为保持静态数据线程安全,我们则需使用类级别锁,这意味着,如果在运行时有多个实例的Test,则一次只能在一个实例中的一个线程上执行一个线程LockMethod(),而所有其他实例将被其他线程锁定。针对类级别锁,那么同步块中监视器或锁定对象有如下三种形式:

    classTest {public synchronized static voidLockMethod() {

    }

    }

    classTest {public voidLockMethod() {synchronized (Test.class)

    {

    }

    }

    }

    classTest {private final static Object lock = newObject();public voidLockMethod() {synchronized(lock) {

    }

    }

    }

    在这里我主要是看到了上述第二种形式中所使用的锁定对象,由于java和C#语法大多相似,但是这在C#中找不到可对比的东西,我不明白这到底是什么个意思,所以就深入看了些,本以为可以直接查看源码,然而并没有任何反应,看来就是Java中天然存在的了,我去打印发现和获取实例的类名的结果是一样的,我们将这种情况翻译为className.class,这到底是什么意思呢?为何上述第二种形式就是类级别锁定从而保证线程安全了呢?

    System.out.println(Test.class.toString());

    System.out.println(new Test().getClass());

    d3aa0f0e23240f4abe83b5192b82ca81.png

    于是乎我想到看一下所购买的《深入理解Java虚拟机》中对于类加载原理的解释,结果发现:在类加载时机的第一阶段也就是加载阶段,虚拟机会完成3件事情,其中最后一件事情则是在内存中生成一个对应类的java.lang.Class对象,作为方法区这个类的各种数据的入口。换句话说,每个类在JVM中有且只会有唯一的一个java.lang.Class对象,所以我大胆猜测className.class就是获取java.lang.Class对象唯一引用,如此一来就保证始终只有一个线程能够进入同步块。

    总结

    本节我们通过对关键字synchronized实现线程同步做了详细了解,其实并不难,这里我想表达的是看到和C#中不一样的东西,也就是className.class具体是什么意思,同时在用java实现单例模式中也有这种情况,所以详细学习了下,也做个备忘录,可能对大部分学java的童鞋而言确实很简单,我还是处于初级阶段,也是在一步步深入的学习。

    展开全文
  • Java 的jdk级别主要是在JUC包下,包括atomic包下的乐观和locks包下的悲观。今天来介绍一下locks包下的悲观(由于百家号对markdown支持不好,代码只能以图片的方式展示了)ReentrantLockReentrantLock实现了...

    Java 的jdk级别的锁主要是在JUC包下,包括atomic包下的乐观锁和locks包下的悲观锁。今天来介绍一下locks包下的悲观锁(由于百家号对markdown支持不好,代码只能以图片的方式展示了)

    ReentrantLock

    ReentrantLock实现了Lock接口,是可重入锁,它是支持公平锁和非公平锁的。下面从加锁和解锁的过程分析一下ReentrantLock。

    1、加锁lock()

    lock操作是分为公平和非公平两种方式的,公平锁顾名思义就是先到先得,先到的线程先拿到锁,后到的线程需要排队,等到前面的线程释放锁之后才能拿到锁,这种方式的缺点是吞吐量小,因为在等待CPU的调度是需要耗费时间的;非公平锁是先去尝试获取锁,如果拿到锁就成功了,如果拿不到再去排队获取锁,这种方式相比公平锁而言,就少了唤醒排队锁时所需要的时间,吞吐量会比公平锁高。

    ReentrantLock和AQS使用了模板设计模式,固定的处理方法都在AQS抽象类中

    非公平锁的lock

    8dc96ab7e3586ddcbfcc5693feee57cf.png

    公平锁的lock

    8e188a08c3bec5098771bbd278883f0b.png

    对于公平锁和非公平锁都用到的方法,都是在AQS中,如下:

    3df7c73237881bb55bc838b9b7d72334.pngaddWaiter方法构造一个Node放到队尾

    7dd049a044f5fd9d5acf57fe0c1d1aee.png

    68743ac886af23824de7cb985d13f729.png

    2、解锁unlock()

    unlock方法调用了AQS的release方法

    11f875460c1619eda642f7441ad9bd34.png

    在ReentrantLock中重写了tryRelease方法,主要操作就是把state值减一

    63c6f9623858d044bffddd30b18fe2c5.png

    tryRelease成功之后,就要去唤醒它的继任者,unparkSuccessor同样是在AQS中实现

    566fba209700aff95bb075d70d159b95.png

    3、使用

    在源码中,也给出了简单的使用例子,但是我觉得在jdk源码中的类LinkedBlockingQueue使用ReentrantLock还是比较适合参照的,下面以代码的形式展示ReentrantLock的使用方式

    cbd94734319e9a1e102a017f529405a2.png

    ReentrantLock就介绍到这了,明天继续更文Lock相关知识

    展开全文
  • 对象级别锁定Java中的每个对象都有一个唯一的。如果线程要在给定对象上执行同步方法,则首先必须获得该对象的。一旦线程获得了,就可以在该对象上执行任何同步方法。一旦方法执行完成,线程将自动释放。JVM...

    两个对象级锁和类级别LOC k的用于实现同步机制在多线程应用程序。

    对象级别锁定

    Java中的每个对象都有一个唯一的锁。如果线程要在给定对象上执行同步方法,则首先必须获得该对象的锁。一旦线程获得了锁,就可以在该对象上执行任何同步方法。一旦方法执行完成,线程将自动释放锁。JVM负责内部获取和释放锁。对象级锁是一种机制,当我们要同步非静态方法或者非静态代码块,使得只有一个线程就可以在类的给定实例执行的代码块。始终可以这样做,以使实例级数据成为线程安全的。

    示例public class ObjectLevelLockTest implements Runnable {

    @Override

    public void run() {

    objectLock();

    }

    public void objectLock() {

    System.out.println(Thread.currentThread().getName());

    synchronized(this) {

    System.out.println("Synchronized block " + Thread.currentThread().getName());

    System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");

    }

    }

    public static void main(String[] args) {

    ObjectLevelLockTest test1 = new ObjectLevelLockTest();

    Thread t1 = new Thread(test1);

    Thread t2 = new Thread(test1);

    ObjectLevelLockTest test2 = new ObjectLevelLockTest();

    Thread t3 = new Thread(test2);

    t1.setName("t1");

    t2.setName("t2");

    t3.setName("t3");

    t1.start();

    t2.start();

    t3.start();

    }

    }

    输出结果t1

    t2

    t3

    Synchronized block t1

    Synchronized block t3

    Synchronized block t1 end

    Synchronized block t3 end

    Synchronized block t2

    Synchronized block t2 end

    类锁

    Java中的每个类都有一个唯一的锁,它只不过是一个类级别的锁。如果线程要执行静态同步方法,则线程需要类级锁。一旦线程获得了类级别的锁,便可以执行该类的任何静态同步方法。一旦方法执行完成,线程将自动释放锁。的类级锁防止多个线程在进入同步块中的任何运行时所有可用的实例。

    示例public class ClassLevelLockTest implements Runnable {

    @Override

    public void run() {

    classLock();

    }

    public void classLock() {

    System.out.println(Thread.currentThread().getName());

    synchronized(ClassLevelLockTest.class) {

    System.out.println("Synchronized block " + Thread.currentThread().getName());

    System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");

    }

    }

    public static void main(String[] args) {

    ClassLevelLockTest test1 = new ClassLevelLockTest();

    Thread t1 = new Thread(test1);

    Thread t2 = new Thread(test1);

    ClassLevelLockTest test2 = new ClassLevelLockTest();

    Thread t3 = new Thread(test2);

    t1.setName("t1");

    t2.setName("t2");

    t3.setName("t3");

    t1.start();

    t2.start();

    t3.start();

    }

    }

    输出结果t3

    t2

    t1

    Synchronized block t3

    Synchronized block t3 end

    Synchronized block t2

    Synchronized block t2 end

    Synchronized block t1

    Synchronized block t1 end

    展开全文
  • Java中,synchronized代码块一次只能由一个线程执行。此外,java支持并发执行...线程持有该方法的对象的监听或对象。如果另一个线程正在执行同步方法,那么您的线程将被阻塞,直到该线程释放监听为止。请注意,...

    在Java中,synchronized代码块一次只能由一个线程执行。此外,java支持并发执行多个线程。这可能导致两个或多个线程同时访问相同的字段或对象。

    同步是保持执行中的所有并发线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步的;线程持有该方法的对象的监听或锁对象。如果另一个线程正在执行同步方法,那么您的线程将被阻塞,直到该线程释放监听为止。

    请注意,我们可以在类中对已定义的方法或块使用synchronized关键字。synchronized关键字不能与类定义中的变量或属性一起使用。

    1. Java中的对象级锁定

    对象级锁是一种机制,当我们想要同步一个非静态方法或非静态代码块时,这样只有一个线程能够在类的给定实例上执行代码块。应该始终这样做,以使实例级数据线程安全。

    对象级锁定可以如下所示:

    public class DemoClass

    {

    public synchronized void demoMethod(){}

    }

    or

    public class DemoClass

    {

    public void demoMethod(){

    synchronized (this)

    {

    //other thread safe code

    }

    }

    }

    or

    public class DemoClass

    {

    private final Object lock = new Object();

    public void demoMethod(){

    synchronized (lock)

    {

    //other thread safe code

    }

    }

    }

    2. Java中的类级别锁

    类级锁防止多个线程在运行时的任何可用类实例中进入同步块。这意味着如果在运行时有100个DemoClass实例,那么每次只有一个线程能够在任何一个实例中执行demoMethod(),而其他所有实例对于其他线程来讲都是被锁定的。

    应该始终执行类级锁定,以使静态数据线程安全。正如我们所知道的,static关键字将方法的数据关联到类级别,因此在静态字段或方法上使用锁定将其关联到类级别。

    参照下面类级别锁定的例子:

    public class DemoClass

    {

    //Method is static

    public synchronized static void demoMethod(){

    }

    }

    or

    public class DemoClass

    {

    public void demoMethod()

    {

    //Acquire lock on .class reference

    synchronized (DemoClass.class)

    {

    //other thread safe code

    }

    }

    }

    or

    public class DemoClass

    {

    private final static Object lock = new Object();

    public void demoMethod()

    {

    //Lock object is static

    synchronized (lock)

    {

    //other thread safe code

    }

    }

    }

    3. 对象级别锁定与类级别锁定 - 重要说明

    Java中的同步确保没有两个线程可以同时或并发地执行需要相同锁的同步方法。

    synchronized关键字只能用于方法和代码块。这些方法或块可以是静态的,也可以是非静态的。

    每当线程进入Javasynchronized方法或块时,它就获得一个锁;每当线程离开synchronized方法或块时,它就释放锁。即使线程在完成后或由于任何错误或异常离开synchronized方法,也会释放锁。

    Java synchronized关键字本质上是可重入的,这意味着如果一个synchronized方法调用另一个需要相同锁的synchronized方法,那么持有锁的当前线程可以在不获取锁的情况下进入该方法。

    如果同步块中使用的对象为空,Java同步将抛出NullPointerException。例如,在上面的代码示例中,如果锁初始化为null,synchronized (lock)将抛出NullPointerException。

    Java中的同步方法会给应用程序带来性能损失。所以在绝对需要的时候使用同步。另外,考虑使用同步代码块只同步代码的关键部分。

    静态同步和非静态同步方法可能同时或并发地运行,因为它们锁定不同的对象。

    根据Java语言规范,不能在构造函数中使用synchronized关键字。这是非法的,会导致编译错误。

    不要在Java同步块的非final字段上同步。因为非final字段的引用可能随时改变,不同的线程可能在不同的对象上同步,即根本没有同步。

    不要使用String文字,因为它们可能在应用程序的其他地方被引用,并可能导致死锁。使用new关键字创建的String对象可以安全地使用。但是最好是,创建一个新的私有范围的对象实例,或者锁定我们想要保护的共享变量本身。

    参考资料:

    展开全文
  • 对象级别锁 vs 类级别锁我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或...
  • Java使用的概念来限制对共享资源或对象的并发访问。可以应用于两个级别-对象级-当您希望非静态方法或非静态代码块仅应由一个线程访问时,可以使用它。类级别锁-当我们要防止多个线程在运行时所有可用实例中的...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...
  • 实例级别 实例代码 复制代码 @Slf4j public class AddCompareDemo { private int a, b; public void add() { for (int i = 0; i < 10000; i++) { a++; b++; } } public void compare() { for ...
  • Java级别

    2018-02-08 17:05:40
    对象和方法其实是同一个东西java的对象和类java的对象和类的概念上基本上和内置是一致的,但是,两个实际是有很大的区别的,对象是用于对象实例方法,或者一个对象实例上的,类是用于类的...
  • Java锁

    2020-10-16 11:21:23
    Java锁synchronizedLockRedisLock Java中的锁包含重量锁、轻量锁、偏向锁、分布式锁。 synchronized synchronized是Java中自带的锁,加锁时使用操作系统互斥量实现,因此synchronized属于一种重量级锁。Jvm对...
  • 对象级别锁 vs 类级别锁我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或...
  • JAVA LOCK 大全 [TOC] 一、广义分类:乐观/悲观 1.1 乐观的实现CAS (Compare and Swap) 乐观适合低并发的情况,在高并发的情况下由于自旋,性能甚至可能悲观更差。 CAS是一种算法,CAS(V,E,N),V:要...
  • 对象级别锁 vs 类级别锁我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...
  • JAVA LOCK 大全[TOC]一、广义分类:乐观/悲观1.1 乐观的实现CAS (Compare and Swap)乐观适合低并发的情况,在高并发的情况下由于自旋,性能甚至可能悲观更差。CAS是一种算法,CAS(V,E,N),V:要更新的变量 ...
  • 最近在做web商城的购物车、订单和库存涉及到了事务及数据库的机制,刚刚看到数据库级别机制,暂且先做个记录 业务场景:当用户下单时,需要减少库存。减少库存操作需要考虑,用户下单的并发,在没有及事务...
  • java程序级别的线程

    2019-07-19 09:55:32
    今天看了并发实践这本书的ReentantLock这章,感觉对ReentantLock还是不够熟悉,有许多疑问,所有在网上找了很多文章看了一下,总体说的不够详细,重点和焦点问题没有谈到...本文我们继续来探讨这个问题,从Java 5之...
  • 浅谈java中的锁级别

    2017-08-30 15:35:32
    进行分级的说明
  • 对于多线程(并发)和Spring Boot这两块在同步进行学习...对象级别锁 vs 类级别锁 我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...
  • java锁

    2020-12-06 22:31:20
    比较交换是多个语句,在硬件级别加lock缓存行锁(超过64K总线)实现原子操作。 CAS ABA问题: 线程1拿到预期值,线程2执行快,把值改变了,又改为原来的值,线程1比较发现是原来的值(本质变了)。通过加版本号,...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...
  • java同步以及级别升级的理解

    千次阅读 2018-07-31 19:48:20
    首先简单说下先偏向、轻量级、重量级三者各自的应用场景: 偏向:只有一个线程进入临界区; 轻量级:多个线程交替进入临界区; 重量级:多个线程同时进入临界区。 还要明确的是,偏向、轻量级都...
  • 在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放。在从 wait()返回前,线程与其他线程竞争重新获得。如果调用 wait()时,...
  • java锁实现

    2018-11-16 20:28:03
    java中的一共有4种状态,级别从低到高分别是: 无锁状态 偏向 轻量级 重量级 只能升级,不能降级 偏向 顾名思义,为了让线程获得的代价更低,引入了偏向。 加锁 当一个线程访问同步块并且获取时...
  • Java锁升级过程

    2020-09-11 15:49:12
    Java锁升级过程Java对象头二、锁种类三、具体过程 Java对象头 synchronized用的锁存在Java对象头里,Java对象头里的Mark Word默认存储对象的HashCode、分代年龄和锁标记位。在运行期间,Mark Word里存储的数据会随着...
  • java 4

    2014-07-16 01:55:00
    java 4 关于的分类 及的灵活使用: 参见http://blog.csdn.net/qaz13177_58_/article/details/21543515 有几句话说得相当不错: 的分类 : 同步分为类级别和对象级别,分别对应着类和对象...
  • Java支持多线程来执行。这可能会导致两个或多个线程访问同一个字段或对象。同步是一个使所有并发执行的线程同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当一个方法被声明为同步时,如果一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,007
精华内容 402
关键字:

java锁级别

java 订阅