`

Java 线程同步几种方式

阅读更多

为何要使用同步? 

    java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 
    将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 
    从而保证了该变量的唯一性和准确性。
1.同步方法 
    即有synchronized关键字修饰的方法。 
    由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 
    内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
    代码如: 
    public synchronized void save(){}
   注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类
2.同步代码块 
    即有synchronized关键字修饰的语句块。 
    被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
    代码如: 
    synchronized(object){ 
    }
    注:同步是一种高开销的操作,因此应该尽量减少同步的内容。 
    通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 
3.使用特殊域变量(volatile)实现线程同步
    a.volatile关键字为域变量的访问提供了一种免锁机制, 
    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, 
    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 
    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 
     注:多线程中的非同步问题主要出现在对域的读写上,如果让域自身避免这个问题,则就不需要修改操作该域的方法。 
    用final域,有锁保护的域和volatile域可以避免非同步的问题。 
4.使用重入锁实现线程同步
    在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。 
    ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 
    它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力
    ReenreantLock类的常用方法有:
        ReentrantLock() : 创建一个ReentrantLock实例 
        lock() : 获得锁 
        unlock() : 释放锁 
    注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 
 
注:关于Lock对象和synchronized关键字的选择: 
        a.最好两个都不用,使用一种java.util.concurrent包提供的机制, 
            能够帮助用户处理所有与锁相关的代码。 
        b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 
        c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 
 
5.使用局部变量实现线程同步 
    如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 
    副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
    ThreadLocal 类的常用方法
    ThreadLocal() : 创建一个线程本地变量 
    get() : 返回此线程局部变量的当前线程副本中的值 
    initialValue() : 返回此线程局部变量的当前线程的"初始值" 
    set(T value) : 将此线程局部变量的当前线程副本中的值设置为value
 

Volatile与Synchronized

对于volatile修饰的变量,当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的

volatile变量对所有线程是立即可见的,对volatile变量的所有写操作都能立刻反应到其他线程之中

JVM规范规定了任何一个线程修改了volatile变量的值都需要立即将新值更新主内存中, 任何线程任何时候使用到volatile变量时都需要重新获取主内存的变量值

两者区别

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化(禁止指令重排序优化,即执行顺序与程序顺序一致);synchronized标记的变量可以被编译器优化

 

分享到:
评论

相关推荐

    java线程同步实例

    根据提供的信息,我们可以深入探讨Java线程同步以及代码示例中的关键知识点。 ### Java线程同步实例:哲学家就餐问题 #### 1. 哲学家就餐问题简介 哲学家就餐问题是多线程编程中一个经典的同步问题。该问题描述为...

    线程的几种控制方式以及线程间的几种通信方式

    3. **线程同步**:为了避免多个线程同时访问共享资源导致数据不一致,引入了线程同步机制。主要包括Java的`synchronized`关键字、Python的`Lock`对象等。 4. **线程间通信**:线程间通信允许线程之间交换信息,Java...

    Java多线程知识点总结

    在Java中,创建线程有几种常见的方式。第一种是通过继承Thread类并重写run方法来定义新的线程类。当创建此类的对象时,实际上就创建了一个新的线程。要启动线程,需要调用线程对象的start方法,这将让线程进入就绪...

    JAVA单线程多线程

    `synchronized`是Java中用于实现线程同步的关键字之一。它可以用来修饰方法或者代码块,确保被修饰的代码在同一时刻只能被一个线程访问。这是Java实现线程安全的一种基本手段。 ##### 使用synchronized修饰方法 当...

    java线程入门级书籍

    线程间通信是指线程之间传递消息或数据的过程,主要包括以下几种方式: - **wait()和notify()方法**:这两个方法用于控制线程间的同步,`wait()`会使当前线程等待直到其他线程调用`notify()`或`notifyAll()`。 - **...

    JAVA线程dump的分析

    在分析JAVA线程dump时,需要注意以下几点: 1. 不同的JAVA虚拟机的线程dump的创建方法和文件格式是不一样的,不同的JVM版本,dump信息也有差别。 2. 在实际运行中,往往一次dump的信息,还不足以确认问题,建议产生...

    java 线程同步

    Java线程同步是多线程编程中的一个关键概念,它涉及到如何在并发环境中控制线程对共享资源的访问,以避免数据不一致性和竞态条件等问题。在Java中,线程同步主要有以下几种机制: 1. **synchronized 关键字**: - ...

    java线程同步操作实例详解

    Java线程同步操作是指在多线程编程中,为了避免线程之间的数据不一致和混乱,采取的一种机制,以确保线程安全。Java提供了多种方式来实现线程同步,包括synchronized关键字、Lock接口、Atomic变量等。 一、...

    Java线程同步方法实例总结

    在Java线程同步中,需要注意以下几点: 1. 使用合适的同步方法:Java提供了多种线程同步方法,开发者需要根据实际情况选择合适的同步方法。 2. 防止死锁:在使用线程同步时,需要防止死锁的出现。 3. 考虑性能问题...

    介绍 Java 多线程 的PPT

    在Java中,实现多线程有两种主要方式:继承`Thread`类和实现`Runnable`接口。 1. **继承Thread类**:创建一个新的类,该类继承自`Thread`类,然后覆盖`run()`方法。在`run()`方法中编写线程要执行的代码。创建了...

    java线程实战手册

    3. **线程同步机制**:Java提供了多种同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口(如ReentrantLock)等,用于防止多个线程并发访问共享资源时产生的数据不一致性问题。...

    Java线程间的通信方式详解

    本文将详细介绍两种常见的Java线程通信方式:同步和while轮询。 1. 同步(Synchronized) 同步是Java中控制线程并发的一种手段,它通过`synchronized`关键字实现。在Java中,同步主要有两种形式:同步方法(通过在...

    电子书《java线程》

    《Java线程》这本书是Java开发人员深入理解并发编程的重要参考资料。Java作为一种广泛使用的编程语言,其并发处理能力是高效程序设计的关键。本电子书详细介绍了如何在Java环境中有效地使用多线程,优化程序性能,并...

    JAVA100例之实例64 JAVA线程间通讯

    在"JAVA100例之实例64 JAVA线程间通讯"这个主题中,我们将深入探讨Java中实现线程间通信的几种主要方法。 1. **共享数据**:最直观的线程间通信方式是通过共享内存空间,即共享变量。只要对共享变量的操作是线程...

    Java线程讲解Java线程讲解

    本篇内容将围绕Java线程的基础知识、创建方式、生命周期以及线程同步等核心概念进行深入探讨。 #### 一、Java线程基础知识 1. **线程与进程的区别**:线程是进程中可独立调度和执行的基本单元,而进程则是资源分配...

    java 多线程并发实例

    在Java中,创建线程主要有两种方式:继承Thread类和实现Runnable接口。在提供的实例中,我们可能会看到这两种方式的运用。 1. 继承Thread类:通过创建新的Thread子类并重写其run()方法,然后创建该子类的实例并调用...

    实现线程同步的几种方式 - Small_Lee的博客 - CSDN博客.html

    java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证...

    基于java 线程的几种状态(详解)

    基于Java线程的几种状态详解 Java线程的状态是一个复杂的概念,它们之间的转换关系也非常重要。下面我们将详细解释Java线程的六种状态:New、Runnable、Blocked、Waiting、Timed waiting和Terminated。 1. 新创建...

    java 多线程交互简单范例

    这种方式称为条件变量,是实现线程同步的一种常见策略。 在`Producer`和`Consumer`线程的交互过程中,可能还会用到阻塞队列(如`java.util.concurrent`包中的`BlockingQueue`接口)等高级并发工具,它们内置了线程...

Global site tag (gtag.js) - Google Analytics