博客
关于我
多线程--Synchronized
阅读量:612 次
发布时间:2019-03-12

本文共 1793 字,大约阅读时间需要 5 分钟。

为什么要使用 synchronized

在并发编程中,线程安全问题是很常见的,主要形式包括共享数据和多线程同时操作共享数据。为了应对这些挑战,Java提供了synchronized关键字,它在以下方面发挥着重要作用:

  • 线程互斥:保证在任何时刻,只有一个线程能够执行同步代码。
  • 可见性:确保共享变量的修改能够及时可见,类似于volatile关键字。
  • 例如,在下面的代码中,如果不使用synchronized,可能会导致火车票重复出售的问题:

    public class TestDemo implements Runnable {    private volatile int count = 100;    @Override    public void run() {        while (count > 0) {            Thread.sleep(50);            sale();        }    }    public void sale() {        if (count > 0) {            System.out.println(Thread.currentThread().getName() + "出售 :" + (100 - count + 1));            count--;        }    }}

    synchronized 的实现原理

    synchronized 的作用机制可以分为以下几个方面:

    • 原子性:确保线程对共享资源的访问是原子操作,避免由于线程调度而导致的竞态条件。
    • 可见性:通过 EnsureIntrinsicLocks 到主内存(当获取锁时)和 UnlockToMemory palpate(解锁前)来保证共享变量的修改能够及时可见。
    • 有序性:排除重排序问题,确保线程间操作的有序性。

    synchronized 的三种应用方式

    在 Java 中,synchronized 锁可以应用在三个不同的方式中:

  • 普通同步方法(实例方法)

    • 锁是当前实例对象。
    • 使用 synchronized修饰方法时,进入方法前需要获取当前实例对象的锁。
    public synchronized void sale() {    if (count > 0) {        System.out.println("窗口一出售 :" + (100 - count));        count--;    }}
  • 静态同步方法

    • 锁是当前类对象。
    • 使用 synchronized修饰静态方法时,进入方法前需要获取当前类对象的锁。
    public static synchronized void sale() {    if (count > 0) {        System.out.println("窗口一出售 :" + (100 - count));        count--;    }}
  • 同步代码块

    • 锁是括号内的对象。
    • 在代码块中使用 synchronized时,进入方法前需要获取括号内对象的锁。
  • private Object object = new Object();public void sale() {    synchronized (object) {        if (count > 0) {            System.out.println("窗口一出售 :" + (100 - count));            count--;        }    }}

    synchronized 的 JDK 版本优化

    在 JDK 1.6 之前,synchronized实现的加锁和解锁操作非常重量级,会导致线程上下文切换和额外性能开销。新版本中,synchronized实现了偏向锁机制,结合轻量级锁和冲突检测机制(cas),从而大幅降低锁的开销。

    synchronized 的可重入性

    synchronized是支持可重入锁设计的。这意味着一个线程在持有一个对象锁的情况下,其它线程同样可以请求该对象锁。但必须注意,如果请求的是同一个对象锁,一定会等待;如果请求的是不同的对象锁,则会立即获取。这种方式避免了死锁,而不会导致资源浪费。

    转载地址:http://bwwaz.baihongyu.com/

    你可能感兴趣的文章
    nifi使用过程-常见问题-以及入门总结---大数据之Nifi工作笔记0012
    查看>>
    NIFI分页获取Mysql数据_导入到Hbase中_并可通过phoenix客户端查询_含金量很高的一篇_搞了好久_实际操作05---大数据之Nifi工作笔记0045
    查看>>
    NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
    查看>>
    Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
    查看>>
    NIFI大数据进阶_FlowFile拓扑_对FlowFile内容和属性的修改删除添加_介绍和描述_以及实际操作---大数据之Nifi工作笔记0023
    查看>>
    NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
    查看>>
    NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
    查看>>
    NIFI大数据进阶_NIFI集群知识点_认识NIFI集群以及集群的组成部分---大数据之Nifi工作笔记0014
    查看>>
    NIFI大数据进阶_NIFI集群知识点_集群的断开_重连_退役_卸载_总结---大数据之Nifi工作笔记0018
    查看>>
    NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
    查看>>
    NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
    查看>>
    NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_01---大数据之Nifi工作笔记0033
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
    查看>>
    NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
    查看>>
    NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
    查看>>
    NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
    查看>>
    NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南002---大数据之Nifi工作笔记0069
    查看>>
    NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
    查看>>
    NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
    查看>>