首页 > 其他分享 >线程安全、synchronized和volatile关键字

线程安全、synchronized和volatile关键字

时间:2024-10-17 22:16:51浏览次数:7  
标签:volatile 变量 synchronized 线程 有序性 保证

一、什么是线程安全?

多线程下并发同时对共享数据进行读写,会造成数据混乱 = 线程不安全

当多线程并发访问临界资源时,如果破坏其原子性、可见性、有序性,可能会造成数据不一致。

  • 临界资源:共享资源(同一对象)同时读写,一次仅允许一个线程使用,才可保证其正确性。

1.1 synchronized

synchronized中文意思是同步,也称之为“同步锁”。

synchronized的作用是保证在同一时刻,被修饰的代码块或方法只会有一个线程执行,已达到保证并发安全的效果。

synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。

synchronized可以保证原子性、可见性、有序性。

1.2 原子性

原子性操作指相应的操作是单一不可分割的操作要想在多线程环境下保证原子性,则可以通过锁、synchronized来确保。volatile是无法保证复合操作的原子性

1.3 可见性

可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

对于可见性,Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

1.4 有序性(指令重排)

有序性最终表述的现象是CPU是否按照既定代码顺序执行依次执行指令。

单线程的情况下只要保证最终执行结果正确即可as-if-serial

指令重排序不会影响单个线程的执行,但是会影响到线程并发执行的正确性。也就是说,要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能会导致程序运行不正确。

在Java里面,可以通过volatile关键字来保证一定的“有序性”。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。

二、如何解决线程不安全

2.1 破坏临界资源

2.2 只读

final

2.3 局部变量

每个线程的局部变量会存在栈帧中,会在每个线程的栈帧内存中被创建多份,因此不存在共享。

2.4 ThreadLocal

2.4.1 ThreadLocal是什么?

ThreadLocal也就是线程本地变量。如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程安全问题。

ThreadLocal是整个线程的全局变量,不是整个程序的全局变量。

2.5 volatile

volatile关键字具备两个特性,一是可见性,一是禁止指令重排。

可见性:当一个变量被声明为volatile时,它会告诉编译器和CPU将该变量存储在主内存中,而不是线程的本地内存中。即每个线程读取的都是主内存中最新的值,避免了多线程并发下的数据不一致问题。

有序性:重排序可以分为编译器重排序和处理器重排序,volatile保证有序性,就是通过分别限制这两种类型的重排序。

标签:volatile,变量,synchronized,线程,有序性,保证
From: https://blog.csdn.net/weixin_63908159/article/details/143020767

相关文章

  • Java-三种线程的实现方式
    1.继承Thread类可以通过创建一个新的类继承Thread类,并重写其run方法来实现线程。classMyThreadextendsThread{@Overridepublicvoidrun(){System.out.println("线程运行中:"+Thread.currentThread().getName());//线程要执行的代码......
  • 线程和进程解释和创建
    一、含义:进程:是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源。举例:IDEA,阿里云盘,wegame,steam线程:是进程中的单个顺序控制流,是一条执行路径一个进程如果只有一条执行路径,则称为单线程程序。一个进程如果有多条执行路径,则称为多线程程序。......
  • 并发编程中锁Synchronized和ReentrantLock,CAS,AQS理解
    SynchronizedJAVA关键字,独占式的悲观锁,可重入锁。主要解决多个线程之间的访问资源的同步性,可以保证被他修饰的方法或者代码块在任意时刻只能有一个线程执行早期是重量级锁,JAVA6后引入大量优化,自旋锁,适应性自旋锁,偏向锁,轻量级锁,锁消除,锁粗化减少锁的开销使用方式修饰......
  • C#线程6---并发集合
    简介:   编程需要对基本的数据结构和算法有所了解。程序员为并发情况选择最合适的数据结构,那就需要知道很多事情,例如算法运行时间、空间复杂度,以及大写0标记法等。在不同的广为人知的场景中,我们总知道哪种数据结构更高效。对于并行计算,我们需要使用适当的数据结构。这些数......
  • IO、进程/线程、同步/异步、阻塞/非阻塞
    IO(Input/Output)IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。比如你打开浏览器,访问新浪首页,浏览器这个程序就需要通过网络IO获取新浪的网页。浏览器首......
  • Java多线程编程:深入理解与实践
    java笔记,点击下载在现代软件开发中,多线程编程已成为提高程序性能和响应能力的关键技术之一。Java作为一门高级编程语言,提供了丰富的多线程支持,使得开发者能够轻松地编写并发程序。本文将深入探讨Java多线程的基本概念、实现方式以及最佳实践。多线程的基本概念多线程是指......
  • 一个月学会Java 第20天 多线程
    Day20多线程线程,很重要的概念,因为我们的CPU假如是intel或者amd的都是说一核二线程,假如你的电脑是8核的cpu那基本上就是16线程,如果你的mac的M芯片自然是几核就是几线程。想要查看自己的电脑是几个线程的我们有几种方法,一种直接使用Java运行一串代码,其次我们可以看任务管......
  • 【Linux】进线程间通信之消息队列
    二、消息队列1.什是消息队列​在Linux中,进程间通信(IPC)的消息队列是一种在进程之间传递数据的机制。它允许不同的进程以异步的方式发送和接收消息。2.消息队列的特点消息队列可以实现多个进程之间的通信,一个进程可以向消息队列发送消息,而另一个进程可以从消息队列中......
  • 剖析线程池实现原理
    前置推荐阅读:java并发之线程池使用-CSDN博客自定义实现一个带监控的线程池首先我们继承ThreadPoolExecutor,实现构造函数以及重写beforeExecute和afterExecute两个函数,具体调用我们会在代码实现层面进行详细的分析。importjava.util.concurrent.*;publicclassAsyncTh......
  • 【Linux】<互斥量>解决<抢票问题>——【多线程竞争问题】
    前言大家好吖,欢迎来到YY滴Linux系列,热烈欢迎!本章主要内容面向接触过C++的老铁主要内容含:欢迎订阅YY滴C++专栏!更多干货持续更新!以下是传送门!YY的《C++》专栏YY的《C++11》专栏YY的《Linux》专栏YY的《数据结构》专栏YY的《C语言基础》专栏YY的《初学者易错点》......