JAVA 线程安全

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
简介: 【1月更文挑战第4天】JAVA 线程安全

什么是线程安全:

当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。

线程安全的解决方式:

使用多线程之间同步或使用锁(lock)可以解决线程安全问题。其核心在于将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,然后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。

什么是多线程之间的同步:

多个线程共享同一个资源的环境下,每个线程工作时不会受到其他线程的干扰称之为多线程之间的同步。

解决线程安全:

使用同步代码块:

synchronized(同一个对象) {
    可能会发生线程冲突问题
}

注意:

在同步代码块中,多个线程必须使用的是同一把锁,即同一个对象。

一般情况下,在使用Runnable实现的线程类中,我们会使用this作为锁对象。

在使用Thread继承的线程类中,一般会使用其Class对象(Class对象在JVM中只会创建一次)。

class Ticket{
  private int number = 30;
  public synchronized void sale() {
    if (number > 0) {
      System.out.println(Thread.currentThread().getName() + "卖出第:\t" + (number--) + "\t 还剩下:" + number);
    }
  }
}
public class SaleTicket {
  public static void main(String[] args){
    //创建资源对象
    Ticket tc = new Ticket();
    //创建AA线程、
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 0; i < 40; i++) {
          //卖票
          tc.sale();
        }
      }
    }, "AA").start();
    //创建BB线程、
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 0; i < 40; i++) {
          //卖票
          tc.sale();
        }
      }
    }, "BB").start();
    //创建CC线程、
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 0; i < 40; i++) {
          //卖票
          tc.sale();
        }
      }
    }, "CC").start();
  }
}

注意:如果使用Thread继承的方式实现多线程,那么同步方法需要是一个静态的方法!

使用Lock解决线程安全:

从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。Lock实现提供更广泛的锁定操作可以比使用 synchronized获得方法和声明更好。他们允许更灵活的结构,可以有完全不同的特性,可以支持多个相关的 Condition对象。Lock提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。

相关文章
|
7天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
24 3
|
4月前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
Java并发编程实战:使用synchronized关键字实现线程安全
71 0
|
4天前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
4天前
|
Java 调度
【JavaEE】——线程的安全问题和解决方式
【JavaEE】——线程的安全问题和解决方式。为什么多线程运行会有安全问题,解决线程安全问题的思路,synchronized关键字的运用,加锁机制,“锁竞争”,几个变式
|
1月前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1月前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
55 4
|
1月前
|
SQL 安全 Java
Java 异常处理:筑牢程序稳定性的 “安全网”
本文深入探讨Java异常处理,涵盖异常的基础分类、处理机制及最佳实践。从`Error`与`Exception`的区分,到`try-catch-finally`和`throws`的运用,再到自定义异常的设计,全面解析如何有效管理程序中的异常情况,提升代码的健壮性和可维护性。通过实例代码,帮助开发者掌握异常处理技巧,确保程序稳定运行。
42 0
|
2月前
|
存储 安全 Java
Java-如何保证线程安全?
【10月更文挑战第10天】
|
2月前
|
安全 Java 编译器
Java 泛型深入解析:类型安全与灵活性的平衡
Java 泛型通过参数化类型实现了代码重用和类型安全,提升了代码的可读性和灵活性。本文深入探讨了泛型的基本原理、常见用法及局限性,包括泛型类、方法和接口的使用,以及上界和下界通配符等高级特性。通过理解和运用这些技巧,开发者可以编写更健壮和通用的代码。
|
3月前
|
安全 Java API
java安全特性
java安全特性
34 8