iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java多线程怎么同步优化
  • 790
分享到

Java多线程怎么同步优化

2023-06-15 06:06:52 790人浏览 安东尼
摘要

这篇文章给大家分享的是有关Java多线程怎么同步优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。加入高速缓存带

这篇文章给大家分享的是有关Java多线程怎么同步优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

概述

处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存

加入高速缓存带来了一个新的问题:缓存一致性。如果多个缓存共享同一块主内存区域,那么多个缓存的数据可能会不一致,需要一些协议来解决这个问题。

在Java内存模型中,分为主内存和线程工作内存,线程使用共享数据时,先从主内存中拷贝数据到工作内存,使用完成之后再写入主内存中。

在Java中,有多线程并发时,我们可以使用多线程同步的方式来解决内存一致性的问题。通常我们可以在程序中添加同步来保障数据的安全访问,但是也经常会带来一些同步性能问题,那么本章将针对常见的同步问题给出了一些优化方案。

读写锁

在多线程操作下,如果我们的某些数据经常被读取操作,但非常少的时机被写入操作。这时,如果我们使用synchronized等同步方式,性能会非常低。

这种场景下,我们应该使用读写锁来进行优化。

读写锁的特点:

  • 读写锁维护一对锁,读锁和写锁。

  • 可以共享读,但只能一个写。

  • 读读不互斥,读写互斥,写写互斥。

某些特定的场景,使用读写锁会极大的提高多线程并发操作的效率。因为,读写锁中,读锁不是排它锁,所以可以并发执行,可以非常显著的提高读取效率;只有在写锁时,是排它锁,这时需要等待写锁的释放。

ReetrantReadWriteLock

ReadWriteLock接口

java并发包中ReadWriteLock是一个接口,抽象了读写锁方法:

public interface ReadWriteLock {        Lock readLock();        Lock writeLock();}

ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁。

ReetrantReadWriteLock类

Java并发库中ReetrantReadWriteLock实现了ReadWriteLock接口并添加了可重入的特性。

ReetrantReadWriteLock获取锁顺序有两种模式:

  • 非公平模式(默认):非公平锁主张竞争获取,可能会延缓一个或多个读或写线程,但是会比公平锁有更高的吞吐量。

  • 公平模式:当以公平模式初始化时,线程将会以队列的顺序获取锁。

可重入

ReetrantReadWriteLock锁是可重入的,当然一个线程获取多少次锁,就必须释放多少次锁。

  • 读线程获取读锁之后能够再次获取读锁。

  • 写线程获取写锁之后能再次获取写锁,也可以获取读锁。

锁降级

在读写锁中,锁降级:从写锁变成读锁;锁升级:从读锁变成写锁。

  • ReentrantReadWriteLock是不支持锁升级的,也就是当一个线程持有了读锁,当该线程再次使用写锁时,是不可以的。如果一个线程持有了读锁,则在获取写锁之前,一定要先释放读锁。

  • ReentrantReadWriteLock支持锁降级的,也就是如果当前线程是写锁的持有者,并保持获得写锁的状态,同时又获取到读锁,然后释放写锁的过程。按照获取写锁、获取读锁、再释放写锁的顺序,即写锁能够降级为读锁。

读写锁状态的设计

读写锁的状态是用一个int值来表示的。state(int32位)字段分成高16位与低16位,其中高16位表示读锁个数,低16位表示写锁个数。

例如,当前一个线程获取到了写锁,并且重入了两次,因此低16位是3,并且该线程又获取了读锁,并且重入了一次,所以高16位是2,当写锁被获取时如果读锁不为0那么读锁一定是获取写锁的这个线程。

写时复制

写时复制(Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者同时要求相同资源,他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的。此作法主要的优点是如果调用者没有修改该资源,就不会有副本被创建,因此多个调用者只是读取操作时可以共享同一份资源。

在Java中,Copy on Write这种机制通常用在集合上,在并发访问的情景下,当需要修改JAVA中Containers的元素时,不直接修改该容器,而是先复制一份副本,在副本上进行修改。修改完成之后,将指向原来容器的引用指向新的容器(副本容器)。

写时复制的特点

  • 由于不会修改原始容器,只修改副本容器。因此,可以对原始容器进行并发地读。其次,实现了读操作与写操作的分离,读操作发生在原始容器上,写操作发生在副本容器上。

  • 数据一致性问题:因为修改操作发生在副本上,读操作的线程可能不会立即读取到新修改的数据内容,但最终修改操作会完成并更新容器,因此这是最终一致性。

  • CopyOnWrite容器适用于读多写少的场景。写操作时,需要复制一个容器,会造成很大的内存开销。

  • 不适合于数据的强一致性场合。若要求数据修改之后立即能被读到,则不能用写时复制技术。因为它是最终一致性。

Java写时复制容器类

jdk中提供了CopyOnWriteArrayList类和CopyOnWriteArraySet类,实现了写时复制。

减小锁的粒度

如果我们在一个大的数据操作类里面,大量使用了锁,并且还是同一个锁,这时,我们的多线程同步效率就会变得非常低。

我们可以将数据按照不同的类型及应用场景进行分割,然后用不同的锁进行同步,这样,不同的场景下就不会产生排它锁的冲突问题,可以大大提高同步的效率。

该方案简单来说就是将一个大锁,分割成多个小锁,这样就能显著的提高多线程并发执行的效率。

减小锁的占有时间

如果在一个较大的方法中,我们直接给该方法加了一个锁,但是我们需要同步的地方只是该方法中的一行操作代码,这样就是很糟糕的同步使用方式了。

我们可以将锁细化到使用它的代码行上,而不是整个函数都加锁,这样锁的持有时间就会变少,从而提高了多线程同步的性能。

该方案是将同步块的代码范围减小,从而降低锁的持有时间,达到优化多线程同步性能的目的。

锁粗化

虽然说,减少锁的占有时间可以提高性能,但是有时候,这种方式并不适用。

例如,一个循环中,我们在循环体中,使用了锁,这样反而会降低性能,这时我们应该在循环开始之前加锁,结束之后释放,也就是将锁粗化。

这是为什么呢?

这是因为,频繁的对锁进行请求、释放、状态修改等操作,会造成大量系统资源的消耗,从而降低性能。

ThreadLocal

同步效率低,是因为多线程同步等待造成的,那么我们可以换一个思路,如果让每个线程都持有一份数据,那这样就不会存在竞争的问题了,也就不需要同步锁了。这样就会很大程度上提高多线程并发的性能。

关于ThreadLocal相关实现原理及使用可以参考之前的文章《ThreadLocal线程本地对象原理分析》。

总结

Java中可以使用锁来解决多线程的同步问题,保障了数据的一致性,但也会代理很多问题,本章总结了多线程同步的几种优化方案:

  • 某些特定的场景(大多是读多、写少的场景),使用读写锁会极大的提高多线程并发操作的效率。因为,读写锁中,读锁不是排它锁,所以可以并发执行,可以非常显著的提高读取效率;只有在写锁时,是排它锁,这时需要等待写锁的释放。

  • Java并发库中ReetrantReadWriteLock实现了ReadWriteLock接口并添加了可重入的特性。

  • 写时复制机制可以显著提高并发效率,在并发访问的情景下,当需要修改JAVA中Containers的元素时,不直接修改该容器,而是先复制一份副本,在副本上进行修改。修改完成之后,将指向原来容器的引用指向新的容器(副本容器)。CopyOnWrite容器适用于读多写少的场景。写操作时,需要复制一个容器,会造成很大的内存开销。

  • 通过减小锁的粒度,来提高同步效率。

  • 减小锁的占有时间是指,通过将同步块的代码范围减小,从而降低锁的持有时间,达到优化多线程同步性能的目的。

  • 有时,大量的锁和锁状态修改会造成系统资源的消耗,我们可以通过锁粗化来优化性能。

  • 我们可以换一个思路,使用ThreadLocal来提高多线程并发的性能。

感谢各位的阅读!关于“Java多线程怎么同步优化”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

本文标题: Java多线程怎么同步优化

本文链接: https://www.lsjlt.com/news/278120.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java多线程怎么同步优化
    这篇文章给大家分享的是有关Java多线程怎么同步优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。加入高速缓存带...
    99+
    2023-06-15
  • Java多线程的同步优化的6种方案
    目录概述读写锁ReetrantReadWriteLock读写锁状态的设计写时复制写时复制的特点Java写时复制容器类减小锁的粒度减小锁的占有时间锁粗化ThreadLocal总结概述 ...
    99+
    2022-11-12
  • Java多线程之线程同步
    volatile 先看个例子 class Test { // 定义一个全局变量 private boolean isRun = true; // 从主线程调...
    99+
    2022-11-12
  • Java中怎么实现多线程同步
    今天就跟大家聊聊有关Java中怎么实现多线程同步,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。让我们从JVM的角度来看看锁这个概念:在Java程序运行时环境中,JVM需要对两类线程共...
    99+
    2023-06-17
  • Java中怎样实现多线程同步
    本篇文章给大家分享的是有关Java中怎样实现多线程同步,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。不同步时的代码Bank.java  package&nb...
    99+
    2023-06-17
  • Java中怎么同步多线程静态数据
    本篇文章给大家分享的是有关Java中怎么同步多线程静态数据,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1:直接使用静态同步方法,Java多线程静态数据代码public&nbs...
    99+
    2023-06-17
  • Java如何实现多线程、线程同步
    这篇文章主要介绍了Java如何实现多线程、线程同步的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java如何实现多线程、线程同步文章都会有所收获,下面我们一起来看看吧。1 多线程1.1 进程进程:是正在运行的程...
    99+
    2023-06-30
  • Java中多线程同步类 CountDownLatch
    在多线程开发中,常常遇到希望一组线程完成之后在执行之后的操作,java提供了一个多线程同步辅助类,可以完成此类需求:类中常见的方法:其中构造方法:CountDownLatch(int count) 参数count是计数器,一般用要执行线程的...
    99+
    2023-05-31
    countdownlatch ava tc
  • Java中怎么利用Synchronized实现多线程同步
    这期内容当中小编将会给大家带来有关Java中怎么利用Synchronized实现多线程同步,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。使用同步的原因 在系统中对访类要使用多线程进行访问; 在该类中有 类...
    99+
    2023-06-17
  • Java多线程怎么使用同步工具类CyclicBarrier
    本篇内容介绍了“Java多线程怎么使用同步工具类CyclicBarrier”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 CyclicBa...
    99+
    2023-06-25
  • Java多线程同步工具类CountDownLatch怎么使用
    本篇内容主要讲解“Java多线程同步工具类CountDownLatch怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程同步工具类CountDownLatch怎么使用”吧!简介...
    99+
    2023-07-02
  • Java多线程同步器代码详解
    同步器为每种特定的同步问题提供了解决方案,同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作。最常用的同步器是CountDownLatch和Semaphore,不常用的是Barrier 和ExchangerSemaphoreSem...
    99+
    2023-05-30
    java 多线程 同步器
  • Java多线程之同步工具类CyclicBarrier
    目录1 CyclicBarrier方法说明2 CyclicBarrier实例3 CyclicBarrier源码解析CyclicBarrier构造函数 await方法 nextGene...
    99+
    2022-11-12
  • Java多线程之同步工具类CountDownLatch
    目录1 CountDownLatch主要方法2 CountDownLatch使用例子3 CountDownLatch源码分析构造函数countDown方法countDown方法的内部...
    99+
    2022-11-12
  • Java多线程之同步工具类Exchanger
    目录1 Exchanger 介绍2 Exchanger 实例exchange等待超时 3 实现原理1 Exchanger 介绍 前面分别介绍了CyclicBarrier、CountD...
    99+
    2022-11-12
  • Java多线程之同步锁-lock详解
    目录一、题目描述二、解题思路三、代码详解一、题目描述 题目: 同步锁出现的目的就是为了解决多线程安全问题。 同步锁的几种方式 synchronized 1、同步代码块 2、同步方法 ...
    99+
    2022-11-13
  • Java中多线程同步的原理是什么
    Java中多线程同步的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、线程的先来后到我们来举一个Dirty的例子:某餐厅的卫生间很小,几乎只能容纳一个人如厕。为了保...
    99+
    2023-06-17
  • java多线程之线程同步的方法有哪些
    Java中线程同步的方法有以下几种:1. synchronized关键字:使用synchronized关键字可以实现对代码块、方法或...
    99+
    2023-09-27
    java
  • 怎么在java中实现多线程的互斥与同步
    这篇文章将为大家详细讲解有关怎么在java中实现多线程的互斥与同步,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、线程互斥与同步互斥:指的是多个线程不能同时访问共享变量同步:指的是多个线程...
    99+
    2023-06-15
  • 什么是java线程同步
    线程同步多线程之间调用同一对象时,为了运行的安全和准确性,需要对该对象进行同步,确保每一个线程用到的时候该对象的结果都是正确的,该对象的状态都是合理的,这部分涉及到同步、线程锁等知识点。这部分的只是就涉及到了synchronized、同步锁...
    99+
    2021-01-13
    java入门 java 线程同步
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作