并发编程原理与实战(四)经典并发协同方式synchronized与wait+notify详解

【java并发】 --wait与notify原理 重量级锁通过对象内部的监视器(monitor)实现,其中monitor的本质是依赖于底层操作系统的Mutex Lock实 现,操作系统实现线程之间的切换需要从用户态到内核态的切换,切换成本非常高。前面我们在讲Java对象头的时候,讲到了monitor这个对象,在hotspot虚拟机中,通过ObjectMonitor类来实现monitor。他的锁的获取过程的体现会简单很多. wait 和notif... 阅读详情

并发编程原理与实战(一)精准理解线程的创建和停止

并发编程原理与实战(二)Thread类关键API详解

并发编程原理与实战(三)一步步剖析线程返回值

前面系列文章,我们详细分析了线程创建、运行、停止、返回的过程,点击上面链接快速查看。本文正式进入多线程与并发协同的相关内容的学习。

多线程

从计算机操作系统的发展历程来看,从早期的从头到尾执行一个能直接访问机器的所有资源单一的程序,发展到允许多个由操作系统分配资源,在进程中运独立运行的程序,程序充分利用资源、各个程序公平访问系统资源、程序开发便利性一直是三大的关注点。三大关注点同样适用在线程的发展上,线程有时被称为轻量级进程,大多数现代操作系统将线程(而不是进程)视为系统调度的基本单位。

通过前文我们已经知道,线程主要功能是完成一个特定的任务,其过程可能因为某些因素进入等待状态(如等待IO)而让出CPU,此时允许其他线程执行其他任务有助于提高CPU等系统资源利用率。允许其他线程同时运行的时候,就要考虑多个线程之间公平访问系统资源了,防止单个线程从头到尾独占资源执行,所以这又涉及多个线程之间的相互协作了。

并发协同

关于并发协同的概念,不管是线程互斥,还是线程同步,或者是线程通信,其本质还是描述多个线程同时运行,协作完成一个或者多个任务。就好比团队协作,不同的人做不同的事,但目标是一致的,就是完成老板下达的任务。如果用团队互斥,或者团队同步,或者团队通信去理解团队协作,视乎有些难理解,“协同”本身已经涵盖了“互斥”、“同步”、“通信”等动作,所以我认为用“并发协同”更容易且全面理解多线程之间的并发协作。理解了多线程的目的和并发协同的概念之后,那可能就会问多线程之间是如何协同工作的?jdk中有哪些并发协同的工具了?我们接着往下看。

传统并发协同方式

我们先来看一个经典的题目:如何控制2个线程依次输出1 2 3 4 5 6…?

题目分析:

步骤1:创建2个线程t1,t2。

步骤2:t1运行输出1,t1停止输出(等待t2输出完,进入等待状态)。

步骤3:t2运行输出2,t2停止输出(等待t1输出完,进入等待状态)。

步骤4:循环执行步骤2和步骤3,即t1和t2依次执行”运行<->等待“动作。

想想通过前面的几篇文章,用已掌握的哪些知识可以解决这个问题。在系统掌握并发编程系列(二)详解Thread类的主要属性和方法这篇文章中,详细分析了Thread类的常用方法,其中包含线程启动与执行控制、控制线程运行状态的两类方法。

并发协同方法选用分析:

1、运行线程用run()、start()这个没什么问题。

2、让线程进入等待状态,sleep(long millis)方法、继承Object类的wait()方法可以选择,但是sleep()方法需要指定睡眠时间,我们没办法知道t1(t2)执行完成后需要等t2(t1)多少时间,所以只有wait()方法可以选择。

3、刚好同样继承Object类的的notify()/notifyAll()方法,能将处于等待状态的线程唤醒。那问题又来了,t1(t2)执行完进入等待状态后谁来通知t2(t1)执行?

4、我们是否可以设置一个公共的变量用来标识是否轮到自己执行,线程t1(t2)输出前先判断是否到自己执行,没到的时候先进入等待状态,到了就输出并设置该变量的值为t2(t1)执行,然后唤醒t2(t1)执行。该变量可以初始一个值,让t1或t2先执行。

基于上面分析,我们用代码来实现:

public class ConcurrentCollaboration {
    //输出数字
    private static int num = 1;
    //公共变量,线程执行标识
    private static boolean thread1Run = true;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(num < 10) {
                    //判断是否轮到自己执行
                    while(!thread1Run) {
                        //没到就进入等待
                        t1.wait();
                    }
                    System.out.println(Thread.currentThread().getName() + " output " + num++);
                    thread1Run = false;
                    //执行完输出,通知t2执行
                    t1.notify();
                }
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(num < 10) {
                    //判断是否轮到自己执行
                    while(thread1Run) {
                        //没到就进入等待
                        t2.wait();
                    }
                    System.out.println(Thread.currentThread().getName() + " output " + num++);
                    thread1Run = true;
                    //执行完输出,通知t2执行
                    t2.notify();
                }
            }
        },"t2");
        t1.start();
        t2.start();
    }
}

上面的代码很明显有一个编译错误问题,执行公共变量判断和输出数字是线程的任务逻辑,前面我们已经知道任务逻辑的实现与线程的创建执行时机是分开的,在任务逻辑里面线程对象可能还没有创建,也就是不能用t1.wait(),t1.notify()的方式。那么谁来调用wait()和notify()方法?我们接着往下看。

synchronized与对象监视器锁

回过头来看看wait()和notify()方法的官方注释,分析下相关使用说明。

    /**
     * Causes the current thread to wait until it is awakened, typically
     * by being <em>notified</em> or <em>interrupted</em>.
     * <p>
     * In all respects, this method behaves as if {@code wait(0L, 0)}
     * had been called. See the specification of the {@link #wait(long, int)} method
     * for details.
     *
     * @throws IllegalMonitorStateException if the current thread is not
     *         the owner of the object's monitor
     * @throws InterruptedException if any thread interrupted the current thread before or
     *         while the current thread was waiting. The <em>interrupted status</em> of the
     *         current thread is cleared when this exception is thrown.
     * @see    #notify()
     * @see    #notifyAll()
     * @see    #wait(long)
     * @see    #wait(long, int)
     */
    public final void wait() throws InterruptedException {
        wait(0L);
    }

调用wait()方法迫使当前线程进入等待状态直到被唤醒或中断,如果当前线程不是对象监视器(什么是象监视器?可以理解成一把锁)的拥有者将会抛出非法的锁状态异常。如果当前正处于等待状态的线程被中断,将会抛出中断异常。内部调用wait(long, int)方法实现,顺着这个看看wait(long, int)方法的说明。

/**
 * Causes the current thread to wait until it is awakened, typically
 * by being <em>notified</em> or <em>interrupted</em>, or until a
 * certain amount of real time has elapsed.
 * <p>
 * The current thread must own this object's monitor lock. See the
 * {@link #notify notify} method for a description of the ways in which
 * a thread can become the owner of a monitor lock.
 * <p>
 ...
 * @apiNote
 * The recommended approach to waiting is to check the condition being awaited in
 * a {@code while} loop around the call to {@code wait}, as shown in the example
 * below. Among other things, this approach avoids problems that can be caused
 * by spurious wakeups.
 *
 * <pre>{@code
 *     synchronized (obj) {
 *         while (<condition does not hold> and <timeout not exceeded>) {
 *             long timeoutMillis = ... ; // recompute timeout values
 *             int nanos = ... ;
 *             obj.wait(timeoutMillis, nanos);
 *         }
 *         ... // Perform action appropriate to condition or timeout
 *     }
 * }</pre> 
 ...
 */
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
    if (timeoutMillis < 0) {
        throw new IllegalArgumentException("timeoutMillis value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
        timeoutMillis++;
    }

    wait(timeoutMillis);
}

注释中提到,调用wait(long, int)方法迫使当前线程进入等待状态直到被唤醒或中断或者睡眠时间用完,当前线程必须拥有对象监视器锁,并给出了正确调用wait()方法的示例。如何让一个线程成为对象监视器锁的拥有者,请查看notify()方法。

/**
 * Wakes up a single thread that is waiting on this object's
 * monitor. If any threads are waiting on this object, one of them
 * is chosen to be awakened. The choice is arbitrary and occurs at
 * the discretion of the implementation. A thread waits on an object's
 * monitor by calling one of the {@code wait} methods.
 * <p>
 * The awakened thread will not be able to proceed until the current
 * thread relinquishes the lock on this object. The awakened thread will
 * compete in the usual manner with any other threads that might be
 * actively competing to synchronize on this object; for example, the
 * awakened thread enjoys no reliable privilege or disadvantage in being
 * the next thread to lock this object.
 * <p>
 * This method should only be called by a thread that is the owner
 * of this object's monitor. A thread becomes the owner of the
 * object's monitor in one of three ways:
 * <ul>
 * <li>By executing a synchronized instance method of that object.
 * <li>By executing the body of a {@code synchronized} statement
 *     that synchronizes on the object.
 * <li>For objects of type {@code Class,} by executing a
 *     static synchronized method of that class.
 * </ul>
 * <p>
 * Only one thread at a time can own an object's monitor.
 *
 * @throws  IllegalMonitorStateException  if the current thread is not
 *               the owner of this object's monitor.
 * @see        java.lang.Object#notifyAll()
 * @see        java.lang.Object#wait()
 */
@IntrinsicCandidate
public final native void notify();

调用该方法可以唤醒一个正在等待对象监视器锁的线程,如果有多个线程在等待对象监视器锁,其中任意一个将被选中唤醒。这个方法只能被拥有对象监视器锁的线程调用,要想拥有对象监视器锁,有3种方式可以获取:

(1)执行对象实例的synchronized修饰的方法。例如:

public synchronized void output(String name) {...}

(2)执行synchronized修饰的代码块。例如:

public void output(String name) {
	synchronized(this){
		...
	}
}

(3)对于类对象,执行synchronized修饰的静态方法。例如:

public synchronized static void output(String name) {...}

synchronized是java内置的关键字,其字面意思是”同步,同步的“意思,是实现线程同步的关键机制,其底层基于对象监视器锁实现,所以用该关键字修饰方法或者代码块可以获得对象监视器锁,被synchronized修饰的方法或者代码块,就像一把锁一样,把方法或者代码块锁住,只能由持有该锁的线程访问。synchronized修饰对象方法时,锁对象就是调用该方法的对象;修饰类方法时,锁对象就是当前类的字节码对象;修饰代码块时,需要在synchronized后面用括号指定锁对象,可以是任意类型的对象(如this,Object);

综合上述分析,线程要想通过调用wait()方法进入等待前,需要通过synchronized获得对象监视器锁;要想调用notify()方法唤醒其他线程前,它也是要先成为对象监视器锁的拥有者。结合官方给出的调用示例,可以推断wait()方法和notify()由锁对象进行调用,我们改造下上面的例子来验证这一结论。

public class ConcurrentCollaboration {
    //输出数字
    private static int num = 1;
    //公共变量,线程执行标识
    private static boolean thread1Run = true;
    //锁对象
    private static final Object lockObject = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(num < 10) {
                    //获取锁对象
                    synchronized (lockObject) {
                        //判断是否轮到自己执行
                        while (!thread1Run) {
                            //没到就进入等待
                            try {
                                lockObject.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + " output " + num++);
                        thread1Run = false;
                        //执行完输出,通知t2执行
                        lockObject.notify();
                    }
                }
            }
        },"t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(num < 10) {
                    //获取锁对象
                    synchronized (lockObject) {
                        //判断是否轮到自己执行
                        while (thread1Run) {
                            //没到就进入等待
                            try {
                                lockObject.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + " output " + num++);
                        thread1Run = true;
                        //执行完输出,通知t2执行
                        lockObject.notify();
                    }
                }
            }
        },"t2");

        t1.start();
        t2.start();
    }
}

运行结果:

t1 output 1
t2 output 2
t1 output 3
t2 output 4
t1 output 5
t2 output 6
t1 output 7
t2 output 8
t1 output 9
t2 output 10

例子还可以进一步完善,但我们的主要目的是验证如何使用wait()和notify()来实现基础的线程并发协同,以及谁来调用wait()和notify()的问题,运行结果已经符合我们的预期了。

总结

本文由多线程的概念引出并发协同以及对象监视器锁(synchronized)的概念,在调用wait()和notify()方法前必须先获得对象监视器锁,并讲解了synchronized的使用方法。通过两个线程交替顺序输出数字的经典题目,结合官方说明一步步分析线程如何获得锁,以及wait()和notify()的使用方法。在此我们总结出并发协同的核心思路:弄清楚并发的是什么,什么时候需要协同,谁来等待,谁来唤醒,通过这样的一个分析过程,希望能让大家深刻理解基础的并发协同的方式。

【java】java wait 原理 synchronized ReentrantLock 唤醒顺序 学习一网友交流请问下,synchronized大并发的情况下,等待区的线程entrySet和waitSet里的线程分别对应Thread的哪个状态啊,都是wating吗?entryList是blocking状态吧,waitSet是waiting状态线程的生命周期,blocking和waiting不是同一种状态吗总结如下:synchronized关键字的调用wait方法进入等到的线程和因为拿不到锁而等待线程是否同一种状态?blocking?waiting? 阅读详情

相关推荐

聚类模型-层次聚类

聚类模型 1、层次聚类 2、原型聚类-K-means 3、模型聚类-GMM 4、EM算法-LDA主题模型 5、密度聚类-DBSCAN 6、图聚类-谱聚类 一、层次聚类 一、聚类理论 ​ 一般来说,聚类是在训练样本的标签信息不知的情况下,学习样本内在的性质和规律,将有限的集合划分成ccc类。根据“方以类聚,物以群分”的思想,类内对象尽可能的相似,...

myazi 6502

ConcurrentProgramming:wait()和notify()和synchronized

ConcurrentProgramming:wait()和notify()必须和synchronized一起使用? 在Java里面,wait()和notify()是Object的成员函数,是基础中的基础。为什么Java要把wait()和notify()放在如此基础的类里面,而不是作为像Thread一类的成员函数,或者其他类的成员函数呢? 先看为什么wait()和notify()必须和synchronized一起使用?请看下面的代码: ​ 等待什么?唤醒什么?什么时候等待和唤醒? class MyClass

chuanchengdabing的博客 387

飞凌OK3588-C Linux R4系统下MIPI YUV摄像头CSI尺寸错误排查与极性适配方案

本文详细介绍了在飞凌OK3588-C平台的Linux R4系统下调试MIPI YUV摄像头时遇到的'csi size err'错误排查与极性适配方案。通过分析信号极性、驱动参数调整及FPGA协同调试,提供了从硬件检测到系统级调试的完整解决方案,帮助开发者快速解决类似问题。

bean的博客 258

synchronized关键字及wait()/notify()/notifyAll()详解

概念 JDK官网中对synchronized关键字有如下定义,synchronized关键字可以实现一个简单的策略来防止线程干扰和内存一致性错误,如果一个对象对多线程是可见的,那么对该对象的所有读或者写都将通过同步的方式来进行。具体表现如下: synchronized关键字提供了一种锁机制,能够确保共享变量的互斥访问,从而防止数据不一致问题的出现。 synchronized关键字包括monitor enter和monitor exit两个JVM指令,它能够保证在任何时候任何线程执行到monitor

Lizhj的博客 1973

持续集成介绍及Jenkins自动化测试部署

学习持续集成及jenkins的自动化测试部署

ouihsiad的博客 4575

三模冗余设计

在数字电路设计中,Voter模块(表决器) 和 三模冗余(Triple Modular Redundancy, TMR) 是高可靠性系统的核心设计技术,主要用于容错和抗辐射(如航天、医疗设备等关键领域)。容错机制:若任一模块故障(如SEU,单粒子翻转),其他两个模块仍能保证正确输出。功耗与面积:TMR会显著增加资源占用(约3倍),需权衡可靠性和成本。航天电子:抗辐射芯片(如FPGA)中用于防止单粒子翻转(SEU)。故障检测:可扩展设计以检测并隔离故障模块(如通过BIST)。

qq_45776815的博客 2050

多线程——多线程安全(synchronized和volatile)、wait和notify

假设 count = 0,使用线程一和线程二同时对 count++,预期结果是 count = 2,但是如果是上述情况的话,线程一拿走 0 到他的寄存器进行计算得 1,还没将 1 返回到内存中,线程二就像 内存 中 count 的值 0 拿到了他的寄存器中,然后再进行计算得 1,最后两个线程将其寄存器的值返回到内存中 的 count,结果是 1。当一个线程还没有释放锁,然后又尝试获取锁时,会出现如下情况:第一次获取锁成功,第二次获取锁时,锁还没有被释放,则该线程就会一直处于阻塞状态,直到锁被释放。

AwwzJ_0821的博客 1247

别再只盯着照片了!手把手教你用Python提取大疆照片里的GPS、姿态和RTK数据

本文详细介绍了如何使用Python提取大疆照片中的GPS、姿态和RTK数据,帮助用户解锁无人机拍摄照片中的隐藏元数据。通过实战代码示例,展示了如何解析EXIF格式的定位、姿态和RTK状态信息,并实现批量处理与数据分析,适用于测绘、农业巡检等专业领域。

weixin_30790841的博客 153

java多线程 synchronized关键字与wait机制理论总结

目录 简介 自旋锁与自适应自旋 锁消除 锁粗化 轻量级锁 偏向锁 简介 高效并发是JDK 1.6的一个重要主题,HotSpot虚拟机开发团队在这个版本上花费了 大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spinning)、锁消除(Lock Elimination)、锁粗化(Lock Coarsening)、轻址级锁(Lightweight Locking)、偏...

今天吃了吗的博客 2289

点云最小二乘法拟合曲线

文章目录一、引言 一、引言

dayuhaitang1的博客 2734

【用unity实现100个游戏之19】制作一个3D传送门游戏,实现类似鬼打墙,迷宫,镜子,任意门效果(附项目源码)

本文介绍了Unity中实现传送门效果的完整流程。通过第一人称角色控制器实现移动,使用PortalView脚本和自定义Unlit Shader渲染门内场景,巧妙利用相机位置和旋转同步实现动态视角。重点解决了近裁剪面问题,确保远距离渲染正确性。最后通过PortalTeleporter脚本实现传送功能,检测碰撞并计算相对位置进行瞬移。该方法无需复杂插件,代码简洁高效,适用于各类3D场景中的传送门实现。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1万+

synchronized 与wait、notify的关系,多线程安全 与 线程通信 的关系。

上一篇博客《synchronized 的用法》中讲解了synchronized 关键字的 所有具体用法, 以及它是如何解决多线程安全问题的。 借这篇文章回顾一下线程通信的基础知识,可能这些知识点大家都能略知一二,但实际项目开发中 几个月不用,可能又会忘记一半,对有些概念似是而非、模棱两可,导致业务项目用到时又需要重新学习,这里自己完整总结一次,方便下次使用时查阅。 一、什么是...

晓游的专栏 1万+

Hugging Face快速入门(重点讲解模型(Transformers)和数据集部分(Datasets))

1. Hugging Face是什么,提供了哪些内容 2. Hugging Face模型的使用(Transformer类库) 3. Hugging Face数据集的使用(Datasets类库)

iioSnail的博客 8万+

Java synchronized中的wait/notify机制详解

Java synchronized中的wait/notify机制是基于对象监视器锁实现的线程通信方式。wait()会释放锁并使线程进入等待状态,notify()随机唤醒一个等待线程,notifyAll()唤醒所有线程。使用时必须在同步块内调用,并通过循环检查条件来避免虚假唤醒。该机制适用于生产者-消费者等模式,但要注意IllegalMonitorStateException和丢失唤醒等问题。相比Java 5的Condition接口,wait/notify更简单但不支持多条件。正确使用这一机制是编写可靠并发程

weixin_47242663的博客 1140

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java并发编程01:Java多线程基础(synchronized,volatile,wait/notify)

多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础多线程基础 ...

ncepu_Chen的博客 2738

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

并发编程-线程调度-park、unpark、join、wait、notify

在Java并发编程中,park和unpark是LockSupport类提供的两个静态方法,用于线程的阻塞和解除阻塞。‌park方法用于阻塞当前线程,使其进入等待状态,而unpark方法用于解除被park方法阻塞的线程。这两个方法通常用于实现线程间的同步和通信, 可以替代传统的wait和notify机制,提供更灵活的方式来控制线程的阻塞和唤醒‌。park方法的使用当线程调用park方法时,它会阻塞当前线程,直到以下情况之一发生:1.另一个线程调用了相应线程的unpark方法;2.中断发生;

m0_45164511的博客 1881

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

wait 和 notify 这个为什么要在synchronized 代码块中?

这个是一个典型的经典面试题。其实考察的就是 Synchronized、wait/notify 的设计原理和实现原理。由于 wait/notify 在业务开发整几乎不怎么用到,所以大部分人回答不出来。其实并发这块内容理论上来说所有程序员都应该要懂,不管是它的应用价值,还是设计理念,非常值得学习和借鉴。三、粉丝福利最近很多同学问我有没有java学习资料,我根据我从小白到架构师多年的学习经验整理出来了一份50W字面试解析文档、简历模板、学习路线图、java必看学习书籍、 需要的小伙伴 可以关注我。

sinat_53467514的博客 1351

Java 并发编程初探 synchronized、volatile、wait、notify

类Thread接口Runnable这两种是在Thread类中官方提到的方法a.join join()方法是让a线程先执行,执行完后继续执行主线程。

qq_56892136的博客 1063

Java并发编程(一)——进程和线程、Java对象内存布局、synchronized、wait和notify、park和unpack

Java并发编程(一)——进程和线程、Java对象内存布局、synchronized、wait和notify一、进程和线程二、Java线程2.1 创建线程的四种方式2.2 线程的生命周期2.3 线程的状态转换(API层次)2.4 线程运行原理2.5 守护线程三、Java对象内存布局和对象头四、synchronized与锁升级4.1 synchronized关键字4.2 synchronized的锁升级4.2.1 偏向锁4.2.2 轻量级锁4.2.2.1 轻量级锁流程解释4.2.3 Monitor 原理 (重

weixin_44630656的博客 2093

Java并发-synchronized与wait和notify

synchronized与wait和notifywait和notify/notifyAll基本使用synchronized同步代码块同步方法(静态与非静态)synchronized、wait、notify/notifyAll的底层实现 wait和notify/notifyAll基本使用 在调用wai方法时,线程必须要持有要对象的锁,当调用wai方法后,线程就会释放掉该对象的锁(monitor)。 在调用Thread类的sleep方法时,线程是不会释放掉对象的锁的。 当调用wait时,首先需要确保调用了wa

unicorn_code的博客 629

Java并发编程:wait方法原理与最佳实践

在当今的软件开发领域,Java作为一种广泛使用的编程语言,其并发编程能力尤为重要。特别是在多线程环境下,如何有效地管理线程间的同步和数据共享,是保证系统稳定性和性能的关键。在众多并发知识点中,"wait"方法作为Java并发编程中的重要组成部分,其作用和适用场景不容忽视。想象一个场景,在一个多线程的数据库操作系统中,多个线程需要访问同一个资源,如数据库连接池。如果不对这些线程进行适当的同步,可能会导致数据不一致或资源竞争等问题。此时,"wait"方法就派上了用场。

我是Java程序员廖志伟,感谢朋友们的支持!不定期贡献一篇高品质、过万文字、图文并茂且附有视频解说、满载代码示例注释的良心之作,坚决杜绝粗制乱造。 958

为什么 java wait/notify 必须与 synchronized 一起使用

为什么 java wait/notify 必须与 synchronized 一起使用 这个问题就是书本上没怎么讲解,就是告诉我们这样处理,但没有解释为什么这么处理?我也是基于这样的困惑去了解原因。 synchronized wait/notify 这两个是Java对象都有的属性,表示这个对象的 不用synchronized 会怎么样 lost wake up 参考博客 为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么 面试官:为什么wait()方法要

笔记小屋 3240

为什么wait/notify必须要和synchronized一起使用?

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)在多线程编程中,wait 方法是让当前线程进入休眠状态,直到另一个...

磊哥聊Java 2606

为什么wait/notify必须要强制要求放在synchronized中

为什么wait/notify必须要强制要求放在synchronized中为什么wait/notify必须要强制要求放在synchronized中如果Object.wait()/notify不需要同步为什么要在JVM层面抛异常如果没有wait/notify 为什么wait/notify必须要强制要求放在synchronized中 在日常开发,我们都知道wait/notify有着非常固定的一套模板,就是下面的样子,synchronized同步块包裹着Object.wait()方法,如果不通过同步块包住的话JVM

huanglong0438的专栏 3148

【Java并发编程系列】- wait & notify,park & unpark,ReentrantLock

而ReentrantLock支持多间休息室,有专门等烟的休息室、专门等早餐的休息室,唤醒时也是按休息室来唤醒。ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持。synchronized是那些不满足条件的线程都在一间休息室等消息。有了多个等待区,就可以避免虚假唤醒,从而简化while-wait。每个线程都有一个自己的park对象 ,该对象由。无论是先使用还是后使用,都能恢复被暂停的线程。公平锁:在线程获取锁失败,进入阻塞队列时,被打断了就不用阻塞了,直接停止运行。

m0_68383079的博客 829

为什么wait和notify必须放在synchronized中?

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)在多线程编程中,wait 方法是让当前线程进入休眠状态,直到另一个...

磊哥聊Java 2106
上一篇: 并发编程原理与实战(三)一步步剖析线程返回值
下一篇: 并发编程原理与实战(五)经典并发协同方式伪唤醒与加锁失效原理揭秘
帧栈
博客等级 码龄2年 335粉丝 120原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帧栈

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值