千家信息网

同步访问共享的可变数据synchronized与volatile关键字怎么用

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章将为大家详细讲解有关同步访问共享的可变数据synchronized与volatile关键字怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。synchro
千家信息网最后更新 2026年10月31日同步访问共享的可变数据synchronized与volatile关键字怎么用

这篇文章将为大家详细讲解有关同步访问共享的可变数据synchronized与volatile关键字怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

synchronized 关键字可以保证同一时刻,只有一个线程可以执行某一个方法,或是某一个代码块。

它包含两个特征:1、互斥 2、可见。即同步不仅可以阻止一个线程看到对象处于不一致的状态中,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护的之前所有的修改效果。

java语言规范保证读或者写一个变量时原子的,除非这个变量的类型为long或者double。

读取一个非long或double类型的变量,可以保证返回的值是某个线程保存在该变量中的,即使多线程在没有同步的情况下并发的修改这个变量也是如此。

虽然语言规范保证了线程在读取原子数据的时候,不会看到任意的数值,但是它并不保证一个线程写入的值对于另一个线程是可见的。为了在线程之间进行可靠通信,也为了互斥访问,同步是必要的。

Java代码

public class StopThread {         private static boolean stopRequested = false;             public static synchronized boolean isStopRequested() {             return stopRequested;         }             public static synchronized void setStopRequested(boolean stopRequested) {             StopThread.stopRequested = stopRequested;         }             public static void main(String[] args) {             try {                 new Thread(new Runnable() {                     @Override                    public void run() {                         int i = 0;                         while (!isStopRequested()) {                             System.out.println(i++);                         }                     }                 }).start();                     TimeUnit.SECONDS.sleep(1);             } catch (InterruptedException e) {                 e.printStackTrace();             }             setStopRequested(true);         }     }

上面的synchronized关键字是需要的,如果没有同步的话,这个程序永远不会终止:因为不能保证后台线程何时"看到"主线程对stopRequested的值所做的改变,后台线程永远在循环。

注意:读写方法都要被同步,否则同步就不会起作用。

stopRequested即使没有被同步也是原子的,这些同步方法是为了它的 通信效果 ,而不是为了互斥访问。

volatile 变量可以被看作是一种 "程度较轻的 synchronized";与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 -- 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。

Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的***值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。

Java代码

public class StopThread2 {         private static volatile boolean stopRequested = false;             public static boolean isStopRequested() {             return stopRequested;         }             public static void setStopRequested(boolean stopRequested) {             StopThread2.stopRequested = stopRequested;         }             public static void main(String[] args) {             try {                 new Thread(new Runnable() {                     @Override                    public void run() {                         int i = 0;                         while (!isStopRequested()) {                             System.out.println(i++);                         }                     }                 }).start();                     TimeUnit.SECONDS.sleep(1);             } catch (InterruptedException e) {                 e.printStackTrace();             }             setStopRequested(true);         }     }

单独使用 volatile 还不足以实现计数器,问题在于操作符(++)不是原子的,例如

Java代码

private static volatile int nextSerialNumber = 0;     public static int generaterSerialNumber(){            return nextSerialNumber ++;     }

它在nextSerialNumber域中执行两个操作:首先它读取值,然后写回一个新值,相当于原来的值再加上1。如果第二个线程在***个线程读取旧值和写回新值期间读取这个域,第二个线程就会与***个线程看到同一值,并返回相同的序列号,这个程序会计算出错误结果。

修正generaterSerialNumber的方法的一种方法是:在它的声明中去掉volatile增加synchronized修饰符。这样可以确保多个调用不会交叉存取,确保每个调用都会看到之前所有调用的效果。

***的修正方法是:使用类AtomicLong

Java代码

private static final AtomicLong nextSerialNumber = new AtomicLong();     public static long generaterSerialNumber(){            return nextSerialNumber.getAndIncrement();     }

简而言之,多个线程共享可变数据的时候,每个读或写数据的线程都必须执行同步。如果没有同步,就无法保证一个线程所做的修改可以被另一个线程获知。如果需要线程之间的交互通信,而不需要互斥,volatile修饰符就是一种可以接受的形式,但需要正确的使用。

关于"同步访问共享的可变数据synchronized与volatile关键字怎么用"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

线程 同步 变量 保证 数据 方法 代码 原子 关键 关键字 之间 特性 可变 多个 效果 篇文章 一致 两个 只有 后台 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 手冲咖啡和咖啡机区别 互联网科技公司 保险科技 互联网保险 湖南永感互联网科技有限公司 重生之互联网科技帝国 互联网科技公司的优势 互联网络科技有限公司 互联网的科技创新 宜安科技 互联网金融 北京禾田雨橡互联网科技 互联网科技公司名称 甘肃拓世互联网科技有限公司 科技互联网的估值 全球顶尖互联网科技公司 华中科技大学互联网的牛人 广州燕处互联网科技有限公司 新氧科技和美国互联网有关系吗 互联网科技手抄报图片 杭州科技互联网公司有哪些 互联网领先科技成果宣传视频 易互联网科技有限公司 高科技与互联网 互联网 新科技 北京三清互联网科技 欧洲十大科技互联网公司 金融科技与互联网金融相同和不同 武汉健翔互联网络科技有限公司 互联网科技包装股份有限公司上市 互联网科技平台产品运营 互联网 科技节活动 微视频大赛
0