返回顶部
首页 > 资讯 > 精选 >Java并发编程中Volatile不能保证数据同步
  • 527
分享到

Java并发编程中Volatile不能保证数据同步

2023-06-17 09:06:12 527人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关Java并发编程中Volatile不能保证数据同步,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。通过一个实例去验证volatile修饰的变量并不能保证其数据同步。

这篇文章将为大家详细讲解有关Java并发编程中Volatile不能保证数据同步,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

通过一个实例去验证volatile修饰的变量并不能保证其数据同步。

Java内存模型规定了所有变量都存储在主内存中,每条线程都有自己的工作内存,线程的工作内存保存了被该线程使用到变量的主内存副本拷贝,线程 对变量的所有操作(读取,赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程也不能直接访问对方工作内存中的变量,线程间变量值的 传递均需要通过主内存来完成,线程,主内存,工作内存三者的交互关系如图所示。


Java并发编程中Volatile不能保证数据同步

当一个变量定义成volatile之后, 保证了此变量对所有线程的可见性,也就是说当一条线程修改了这个变量的值,新的值对于其它线程来说是可以立即得知的.此时,该变量的读写操作直接在主内存中完成.

Volatile 变量具有 synchronized 的可见性特性但是不具备原子特性

Volatile variables share the visibility features of synchronized, but none of the atomicity features.

虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。

While the increment operation (x++) may look like a single  operation, it is really a compound read-modify-write sequence of  operations that must execute atomically -- and volatile does not provide  the necessary atomicity.

多线程并发的环境下, 各个线程的读/写操作可能有重叠现象, 在这个时候, volatile并不能保证数据同步.

下面将给出一个实例:

实例 ==> 500个线程一起运行,每个线程对1到100求和1000次操作,然后将一个volatile共享变量值加1. 当500个线程都完成操作之后, 期望的值是500,因为每个线程执行完毕之后都会对这个volatile变量加1.

一直循环执行这个程序,直到出现volatile变量的值小于500为止,也就是出现数据不同步。

public class NonSafeThread implements Runnable {           private volatile int volatileCount = 0;      public void run() {                    for (int i = 1; i <= 1000; i++) {             sum100();         }                    increase();     }          private void increase()     {         volatileCount++;     }           private int sum100() {         int result = 0;         for (int i = 1; i <= 100; i++) {             result += i;         }         return result;     }           public int getVolatileCount() {         return volatileCount;     }  }
  public class NonSafeThreadTest {      public static void main(String[] args) {                   int loopCount = 0;                   ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();          for (;;) {             loopCount++;                           NonSafeThread nonSafeThread = new NonSafeThread();             startThreads(nonSafeThread);                           while (!isOnlyMainThreadLeft(threadGroup)) {                 sleep(5);             }                           validate(loopCount, nonSafeThread.getVolatileCount(), 500);         }     }           private static void startThreads(NonSafeThread nonSafeThread) {          for (int i = 0; i < 500; i++) {             new Thread(nonSafeThread).start();         }     }           private static void validate(int loopCount, int actualValue,             int expectedValue) {         if (!isVolatileCountExpected(actualValue, expectedValue)) {             printNonSafeMessage(loopCount, actualValue, expectedValue);                          System.exit(0);         }     }           private static void printNonSafeMessage(int loopCount, int actualValue,             int expectedValue) {         System.out.println(String.fORMat(                 "第%d次循环,出现线程不安全的情况,volatile的值不正确,期望值是%d, 但是500个线程运行的情况下是%d",                 loopCount, expectedValue, actualValue));     }           private static boolean isVolatileCountExpected(int actualValue,             int expectedValue) {         return actualValue == expectedValue;     }           private static void sleep(long millis) {         try {             Thread.sleep(millis);         } catch (InterruptedException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }     }           private static boolean isOnlyMainThreadLeft(ThreadGroup tg) {         return tg.activeCount() == 1;     }  }

某次运行,输出的结果如下:

第83次循环,出现线程不安全的情况,volatile的值不正确,期望值是500, 但是500个线程运行的情况下是499

在这种情况下,可以通过 Lcak和synchronized来保证数据的同步。

如:

使用Lock,修改NonSafeThread类的run方法的内容:

public void run() {          lock.lock();          try {                           for (int i = 1; i <= 1000; i++) {                 sum100();             }                            increase();                      } finally {             lock.unlock();         }      }

使用synchronized

public void run() {          synchronized ("") {                           for (int i = 1; i <= 1000; i++) {                 sum100();             }                            increase();         }     }

如果用Lock或者synchronized修改了NonSafeThread类,  如果再想跑这个程序的话,需要控制一下NonSafeThreadTest中for循环中执行的次数,比如1000次  (我运行程序的时候,一般都在100次以内打印出数据不安全的结果),以免导致程序在Lock或者synchronized修改后一直执行下去.

关于java并发编程中Volatile不能保证数据同步就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: Java并发编程中Volatile不能保证数据同步

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

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

猜你喜欢
  • Java并发编程中Volatile不能保证数据同步
    这篇文章将为大家详细讲解有关Java并发编程中Volatile不能保证数据同步,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。通过一个实例去验证volatile修饰的变量并不能保证其数据同步。...
    99+
    2023-06-17
  • java并发编程关键字volatile保证可见性不保证原子性详解
    目录关于可见性关于指令重排volatile关键字可以说是Java虚拟机提供的最轻量级的同步机制,但对于为什么它只能保证可见性,不保证原子性,它又是如何禁用指令重排的,还有很多同学没彻...
    99+
    2024-04-02
  • Java中如何打包数组并保证同步?
    在Java中,数组是一种非常重要的数据结构,它可以用来存储一系列相同类型的数据。在实际应用中,我们经常需要将多个数组打包成一个整体进行操作。然而,由于Java是一种多线程语言,我们在打包数组时需要保证线程安全,否则就会出现数据竞争等问题。...
    99+
    2023-06-06
    打包 数组 同步
  • Java并发编程同步器CountDownLatch
    CountDownLatch 在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在 CountDownLatch...
    99+
    2024-04-02
  • Java并发编程之同步容器
    目录简介一、什么是同步容器二、为什么要有同步容器三、同步容器的优缺点四、同步容器的使用场景总结简介 同步容器主要分两类,一种是Vector这样的普通类,一种是通过Collection...
    99+
    2024-04-02
  • java并发编程JUC CountDownLatch线程同步
    目录java并发编程JUC CountDownLatch线程同步1、CountDownLatch是什么?2、CountDownLatch 如何工作3、CountDownLat...
    99+
    2024-04-02
  • Java并发编程(03):多线程并发访问,同步控制
    本文源码:GitHub·点这里 || GitEE·点这里一、并发问题多线程学习的时候,要面对的第一个复杂问题就是,并发模式下变量的访问,如果不理清楚内在流程和原因,经常会出现这样一个问题:线程处理后的变量值不是自己想要的,可能还会一脸懵的...
    99+
    2023-06-02
  • Java并发编程之详解CyclicBarrier线程同步
    CyclicBarrier线程同步 java.util.concurrent.CyclicBarrier提供了一种多线程彼此等待的同步机制,可以把它理解成一个障碍,所有先到达这个障碍...
    99+
    2024-04-02
  • Java并发编程同步器CountDownLatch怎么用
    今天小编给大家分享一下Java并发编程同步器CountDownLatch怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。...
    99+
    2023-06-30
  • Java打包中如何保证函数同步性?
    在Java开发中,函数同步性是非常重要的。如果多个线程同时对同一个函数进行调用,可能会导致数据竞争和死锁等问题,因此我们需要保证函数的同步性。在本文中,我将介绍Java打包中如何保证函数同步性,并提供一些示例代码以帮助您更好地理解这个概念...
    99+
    2023-09-29
    打包 同步 函数
  • PHP 并发编程下的数据结构同步机制
    在 php 并发编程中,以下数据结构同步机制至关重要:临界区:使用 synchronized 关键字保护临界区代码区域,一次仅允许一个线程执行;互斥锁:通过 lock() 和 unloc...
    99+
    2024-05-07
    php 并发编程 同步机制
  • 如何使用Java同步函数生成二维码并保证数据安全?
    Java 是一种流行的编程语言,其语法简单易懂,易于学习。Java 同步函数是一种可以帮助我们生成二维码并保证数据安全的函数,本文将为您详细介绍如何使用 Java 同步函数生成二维码并保证数据安全。 一、Java 同步函数的概念 Java ...
    99+
    2023-10-17
    函数 同步 二维码
  • Java并发编程中volatile关键字有什么作用
    本篇内容主要讲解“Java并发编程中volatile关键字有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java并发编程中volatile关键字有什么作用”吧!1、volatile是什...
    99+
    2023-06-25
  • Laravel中的同步编程:与Python并发编程的异同点
    Laravel是一款流行的PHP框架,而Python也是一门广泛应用的编程语言。在编程语言中,同步编程和异步编程是两个重要的概念。在本文中,我们将探讨Laravel中的同步编程和Python中的异步编程之间的异同点。 同步编程是一种编程方式...
    99+
    2023-09-16
    并发 同步 laravel
  • Java并发编程之同步容器与并发容器详解
    一、同步容器  1、Vector——>ArrayList  vector 是线程(Thread)同步(Synchronized)的,所以它也是线程...
    99+
    2024-04-02
  • java并发编程之同步器代码示例
    同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作。最常用的同步器是CountDownLatch和Semaphore,不常用的是Barrier和Exchanger队列同步器AbstractQueuedSynchronizer是用来...
    99+
    2023-05-30
    java 并发 同步器
  • Java编程中同步关键字如何保证算法的正确性?
    在Java编程中,多线程并发访问共享资源是一个常见的问题。为了避免多线程访问共享资源时可能出现的竞态条件和数据不一致等问题,Java提供了同步机制来保证线程的安全性和正确性。其中,同步关键字synchronized是Java中最常用的同步...
    99+
    2023-11-11
    编程算法 同步 关键字
  • 深入分析java并发编程中volatile的实现原理
    引言在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能...
    99+
    2023-05-30
    java 并发编程 volatile
  • 并发编程中 C++ 函数的锁与同步机制?
    c++++ 并发编程中函数锁和同步机制用于管理多线程环境中数据的并发访问,防止数据竞争。主要机制包括:互斥量 (mutex):低级同步原语,确保一次只有一个线程访问临界区。条件变量 (c...
    99+
    2024-04-27
    c++ 并行编程 并发访问 同步机制
  • Python并发编程中的锁机制,揭秘并发编程中的同步之道
    锁的必要性 在并发编程中,多个线程同时操作共享资源时,如果不采取适当的同步措施,很容易导致数据不一致和程序崩溃等问题。锁机制就是一种常用的同步手段,它可以确保在同一时刻只有一个线程可以访问共享资源。 锁的种类 Python中提供了多种锁...
    99+
    2024-02-05
    Python 并发编程 锁机制 线程安全 数据同步
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作