Java并发之互斥同步、线程之间的协作

详解线程同步和线程互斥,Java如何实现线程同步和互斥 首先第一个问题,为什么进行线程同步和线程互斥?最开始我们的操作系统的作业的调度单位是进程,但是由于每个进程都单独占据一个资源,而且进程的形态转换非常的耗费系统资源。为了系统的调度更加轻量级,能够更好的支持并发,因此引入了线程这个概念。PS:进程和线程的关系:什么是线程同步?什么是线程互斥?线程同步和线程互斥,类似于进程同步和进程互斥,在《操作系统》这本书中有另一个好听的名字:直接制约和间接制约直接制约(同步关系):某些应用程序,为了完成某个任务而建立了两个或多个进程(源于进程间的合作)。间接制约(互斥关系) 阅读详情

目录

 

互斥同步

一、synchronized

二、ReentrantLock:java.util.concurrent(J.U.C)包中的锁。

比较

使用选择

线程之间的协作

join()

wait()  notify()  notifyAll()

await()  signal()  signalAll()


互斥同步

Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。

一、synchronized

1、同步一个代码块

它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。

public class SynchronizedExample {

    public void func1() {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                System.out.print(i + " ");
            }
        }
    }
}

//使用 ExecutorService 执行了两个线程
//由于调用一个对象的同步代码块,因此这两个线程会进行同步
//程进入同步语句块时,另一个线程就必须等待。
public static void main(String[] args) {
    SynchronizedExample e1 = new SynchronizedExample();
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.execute(() -> e1.func1());
    executorService.execute(() -> e1.func1());
}

//结果
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
//两个线程调用了不同对象的同步代码块,因此这两个线程就不需要同步。
//从输出结果可以看出,两个线程交叉执行。
public static void main(String[] args) {
    SynchronizedExample e1 = new SynchronizedExample();
    SynchronizedExample e2 = new SynchronizedExample();
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.execute(() -> e1.func1());
    executorService.execute(() -> e2.func1());
}

//结果
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9

2、同步一个方法

3、同步一个类

作用于整个类,也就是说两个线程调用同一个类的不同对象上的这种同步语句,也会进行同步。

public static void main(String[] args) {
    SynchronizedExample e1 = new SynchronizedExample();
    SynchronizedExample e2 = new SynchronizedExample();
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.execute(() -> e1.func2());
    executorService.execute(() -> e2.func2());
}

//结果
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

4、同步一个静态方法:作用于整个类

public synchronized static void fun() {
    // ...
}

二、ReentrantLock:java.util.concurrent(J.U.C)包中的锁。

public class LockExample {

    private Lock lock = new ReentrantLock();

    public void func() {
        lock.lock();
        try {
            for (int i = 0; i < 10; i++) {
                System.out.print(i + " ");
            }
        } finally {
            lock.unlock(); // 确保释放锁,从而避免发生死锁。
        }
    }
}

public static void main(String[] args) {
    LockExample lockExample = new LockExample();
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.execute(() -> lockExample.func());
    executorService.execute(() -> lockExample.func());
}

//结果
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

比较

1. 锁的实现

synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。

2. 性能

新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。

3. 等待可中断

当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。

ReentrantLock 可中断,而 synchronized 不行。

4. 公平锁

公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。

synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。

5. 锁绑定多个条件

一个 ReentrantLock 可以同时绑定多个 Condition 对象。

使用选择

除非需要使用 ReentrantLock 的高级功能,否则优先使用 synchronized。这是因为 synchronized 是 JVM 实现的一种锁机制,JVM 原生地支持它,而 ReentrantLock 不是所有的 JDK 版本都支持。并且使用 synchronized 不用担心没有释放锁而导致死锁问题,因为 JVM 会确保锁的释放。

 

 

线程之间的协作

join()

在线程中调用另一个线程的 join() 方法,会将当前线程挂起,而不是忙等待,直到目标线程结束。

eg: 如果b 线程先启动,但是因为在 b 线程中调用了 a 线程的 join() 方法,b 线程会等待 a 线程结束才继续执行,因此最后能够保证 a 线程的输出先于 b 线程的输出。

 

wait()  notify()  notifyAll()

调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。

只能用在同步方法或者同步控制块中使用,否则会在运行时抛出 IllegalMonitorStateException。

//使用 wait() 挂起期间,线程会释放锁。
//这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,
//那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。
public class WaitNotifyExample {

    public synchronized void before() {
        System.out.println("before");
        notifyAll();
    }

    public synchronized void after() {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after");
    }
}
public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    WaitNotifyExample example = new WaitNotifyExample();
    executorService.execute(() -> example.after());
    executorService.execute(() -> example.before());
}

//结果
before
after

wait() 和 sleep() 的区别

  • wait() 是 Object 的方法,而 sleep() 是 Thread 的静态方法;
  • wait() 会释放锁,sleep() 不会。
     

await()  signal()  signalAll()

java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。

相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。

public class AwaitSignalExample {

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void before() {
        lock.lock();
        try {
            System.out.println("before");
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void after() {
        lock.lock();
        try {
            condition.await();
            System.out.println("after");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    AwaitSignalExample example = new AwaitSignalExample();
    executorService.execute(() -> example.after());
    executorService.execute(() -> example.before());
}

//结果
before
after


 

Java 并发知识点总结归纳 Java 并发 Java 并发 一、使用线程 实现 Runnable 接口 实现 Callable 接口 继承 Thread 类 实现接口 VS 继承 Thread 二、基础线程机制 Executor Daemon sleep() yield() 三、中断 InterruptedException interrupted() Executor 的中断操作 四、互斥同步 synchronized ReentrantLock 比较 使用选择 五、线程之间的协作 join() wa 阅读详情

相关推荐

java实现多线程间的同步与互斥(读者写者问题)

用java实现多线程并发中的读者与写者问题,能够实现多线程对临界资源的同步有序访问。 具体实现为: 给定一个队列A[1-10][1-100000]、元素编号1-10,其中每个元素包含10万个随机数。创建若干个线程,各循环100次;其中10,100个为读线程,10,100个为更新线程。 1. 读线程每次产生随机数三元组:(i, j, k),其中i: [1-10], j: [1-100000],k[j-100000],求取指定A[i]一级数组中第j到第k个元素的均值; 2. 更新线程每次产生一对随机整数三元组 (i, j, k) 和一个随机浮点数d:(0-1),其中i: [1-10], j: [1-100000],k[j-100000],完成对A[i][j]到A[i][k]之间的所有元素进行数值更新,x = x * (1 + d)

【JAVA 提高班之七】多线程互斥和协作

多线程是个庞大的话题,从不同的角度有不同的讲述,本文专注于从多线程的协作角度,有互斥关系,合作关系,父子关系,线程池。线程状态图的演进一.线程基本状态图 普通的Thread对象通过调用Start()方法进入就绪态(Runnable),在Runnable状态下是可以被CPU调度的,即获取CPU时间片进入运行态调用Run方法,在获取到的时间片结束之后可以继续返回到就绪态。但是如果在运行态发生阻塞式的操

飞翔的美食家 891

LED单元板驱动(HUB75接口)

开始之前先吐槽一下,搜这个的资料。要么都是Arduino,要么单片机的收费。小小的一个LED单元板,凭什么? 用Arduino是你速度快还是我ST,树莓派不好用?收费更离谱,这点东西还藏私?给你个中指凸。把原理都写出来看你怎么收费。 一、接口定义及原理 如图,有两个RGB通道,共占用6个IO。剩下的ABCDE为地址通道,LAT为行数据锁存通道,CLK为数据时钟,OE为低电平使能LED显示。图片这里没有E,证明它是16扫的,有E就会把B上面的地改为E。这样就是5位,2的5次方32扫。1.

a3748622的博客 3万+

java中线程的同步:(互斥,协作)

1.线程同步介绍:       在java中线程同步是多个线程并发执行时,在共享数据集上的互斥与协作; 互斥是为了保证数据的安全,协作是让多个线程在共享数据集上进行通讯,以确保业务的合理性。 2.线程同步FAQ: (1)为什么多个线程在共享数据集上要互斥执行(排队执行),所有的操作都要互斥吗? 什么情况下进行互斥呢?    (2)多线程互斥如何实现呢? (3)多线程在共享数据集上通

system_err的博客 718

光通信仿真入门:手把手教你用VPI和Matlab搭建第一个联合仿真系统(含避坑指南)

本文详细介绍了如何使用VPI和Matlab搭建光通信联合仿真系统,涵盖软件配置、链路搭建、数据交互等关键环节,并提供常见问题的解决方案。特别适合初学者快速掌握光通信仿真技术,避免常见错误,提升仿真效率。

weixin_28733637的博客 377

同花顺【红绿趋势】幅图指标 源码分析

a10:IF(差值<=0 ,0 ,差值*0.2 ,4 ,0),STICK,linethick5,colorred;a7:IF(差值<=0 ,0 ,差值*0.8 ,4 ,0),STICK,linethick5,colorred;a8:IF(差值<=0 ,0 ,差值*0.6 ,4 ,0),STICK,linethick5,colorred;a6:IF(差值<=0 ,0 ,差值*1 ,4 , 0),STICK,linethick5,colorred;DRAWICON(先锋<0,-25,1);

zhibiaogong的博客 4054

java中querywrapper.in()方法_java学习中多线程同步和互斥有哪些实现方法

所谓同步,是指在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。java学习中多线程同步和互斥有哪些实现方法...

weixin_39876002的博客 376

七、永磁同步电机矢量控制(FOC)—MTPA控制及Simulink仿真

前面几节的内容已经完成Id=0控制策略的理论和仿真以及双闭环PI参数整定。在接下来几节中,将陆续讲解MTPA、弱磁控制等内容。

weixin_45182459的博客 8190

Java世界里的同步、协作、互斥、高并发

本文主要解释词汇、磨刀不误砍柴功 先解释概念 互斥行为:资源的某些操作可能是不支持同时多人执行,当多人同时操作时就会触发互斥限制。这些操作必须排成队列按部就班的等待执行,不能并发。任何操作都可以定义为互斥的,常见的修改、删除甚至搜索、添加。 协作行为: 同步行为: 高并发行为:

路演 389

国密系列算法简介

众所周知,为了保障商用密码的安全性,国家商用密码管理办公室制定了一系列密码标准,包括SM1(SCB2)、SM2、SM3、SM4、SM7、SM9、祖冲之密码算法(ZUC)那等等。其中SM1、SM4、SM7、祖冲之密码(ZUC)是对称算法;SM2、SM9是非对称算法;SM3是哈希算法。目前,这些算法已广泛应用于各个领域中,期待有一天会有采用国密算法的区块链应用出现。其中SM1、SM7算法不公开,调用该...

HardessGod的博客 5775

逆向分析踩坑记:当Frida在x86模拟器上‘看不见’ARM的so文件时,我们该如何手动定位与验证?

本文探讨了在x86模拟器上使用Frida进行逆向分析时,无法检测到ARM架构so文件的解决方案。通过分析内存映射、Frida的视觉盲区及手动定位技术,提供了兼容层、混合调试和原生ARM环境三种实用方案,帮助逆向工程师突破工具限制,实现精准定位与验证。

weixin_27697385的博客 221

Java并发编程,互斥同步和线程之间的协作

互斥同步和线程之间的协作 互斥同步 Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。 synchronized 1. 同步一个代码块 public void func() { synchronized (this) { // ... ...

不喝枸杞的程序员 757

超十万字解读Spring AI实战:开篇

大模型技术正以惊人的速度改变世界,2025年的人工智能已不再是科幻,而是现实。大模型如ChatGPT等,正在重塑各行各业,降低技术门槛,使专业能力普及化。SpringAI的出现为Java开发者提供了桥梁,使其能在企业级系统中稳定运行AI,同时保持工程化思维。尽管SpringAI在生态、学习成本和性能上存在不足,但其企业级基因和国产化适配能力使其成为Java开发者的重要工具。本系列文章旨在介绍SpringAI的功能与特性,鼓励更多Java开发者参与AI实践,共同探索AI时代的无限可能。

liaokailin的专栏 1575

java线程协作_Java并发编程,互斥同步和线程之间的协作

互斥同步和线程之间的协作互斥同步Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。synchronized同步一个代码块public void func() {synchronized (this) {// ...}}它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进...

weixin_32380307的博客 124

时间序列预测 | Python实现LSTM时间序列数据预测

目录LSTM神经网络LSTM原理LSTM数据下载LSTM程序设计导入Python包时序数据处理LSTM模块定义模型训练模型评估参数设定运行结果参考资料致谢 LSTM神经网络 长短期记忆网络——通常简称为“LSTM”——是一种特殊的 RNN,能够学习长期依赖关系。它们由Hochreiter & Schmidhuber (1997)引入,并在后续工作中被许多人提炼和推广。1它们在处理各种各样的问题时效果非常好,现在被广泛使用。LSTM 被明确设计为避免长期依赖问题。长时间记住信息实际上是他们的默认行为

前程算法屋的博客 3911

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java线程:并发协作-生产者消费者模型

/**  * Java线程:并发协作-生产者消费者模型  *  * @author leizhimin 2009-11-4 14:54:36  */ public class Test {  public static void main(String[] args

273

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

线程并发之回顾传统线程创建,定时器及线程间的通讯

线程并发之回顾传统线程创建,定时器及线程间的通讯 java开发童鞋们需要掌握线程的使用了。 [java] view plaincopyprint? <PRE class=java name="code">创建线程的两种传统方式</PRE> <DIV>在Thread子类覆盖的run方法中编写运行代码</DIV>...

weixin_30287169的博客 78

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Java并发-线程状态、使用线程、线程机制、中断、互斥、协作-Java基础

JVM的synchronized package pratice717; //JVM的synchronized import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class synchronizedExample { ...

洋葱专栏-有灵魂的程序员 204

Java并发编程原理: 线程之间的互斥与协作机制

可能在synchronized关键字的实现原理中,你已经知道了它的底层是使用Monitor的相关指令来实现的,但是还不清楚Monitor的具体细节。本文将让你彻底Monitor的底层实现...

AI天才研究院 9224

Java多线程编程:深入探索线程同步与互斥的实战策略

在现代编程中,多线程环境已经成为提高应用程序性能和响应速度的重要手段。然而多线程编程也带来了复杂的线程安全问题,特别是在多个线程需要访问共享资源时。为了确保线程安全,同步和互斥技术显得尤为关键。本文将详细介绍Java中实现线程同步与互斥的多种方法,并提供相应的代码案例,以帮助开发者更好地理解和应用这些技术。

Rye的博客 2825

java互斥锁实现线程同步(附带源码)

java互斥锁实现线程同步(附带源码)

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 1300

详细说说线程的同步和互斥

这两个核心并发概念。它们是确保多线程程序正确性、避免竞态条件(Race Condition)和维持数据一致性的基石。你想要的技术资料我全都有:https://pan.q删掉汉子uark.cn/s/aa7f2473c65b。(变量、对象、文件、数据库连接等)的访问,防止它们同时进行可能导致数据损坏或逻辑错误的操作。

牛马baby的博客 1011

java线程同步和线程互斥实现方式

线程同步是指控制多个线程对共享资源的访问顺序,以确保数据的正确性和一致性。在并发编程中,如果多个线程同时访问和修改共享资源(如变量、对象、文件等),可能会导致数据的不一致性。为了解决这个问题,需要通过线程同步机制来确保每次只有一个线程能够访问共享资源,直到该线程完成对资源的操作后,其他线程才能继续访问。线程互斥(Thread Mutual Exclusion)是指防止多个线程同时访问共享资源,从而避免竞态条件和数据不一致问题。

Flying_Fish_roe的博客 1227
上一篇: Java并发之线程、基础线程机制、中断
下一篇: Java线程的状态
trytrylmt
博客等级 码龄9年 7粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值