博客
关于我
多线程--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/

    你可能感兴趣的文章
    Openlayers中使用Cluster实现点位元素重合时动态聚合与取消聚合
    查看>>
    Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合
    查看>>
    Openlayers中使用Image的rotation实现车辆定位导航带转角(判断车辆图片旋转角度)
    查看>>
    Openlayers中点击地图获取坐标并输出
    查看>>
    Openlayers中设置定时绘制和清理直线图层
    查看>>
    Openlayers图文版实战,vue项目从0到1做基础配置
    查看>>
    Openlayers实战:modifystart、modifyend互动示例
    查看>>
    Openlayers高级交互(10/20):绘制矩形,截取对应部分的地图并保存
    查看>>
    Openlayers高级交互(16/20):两个多边形的交集、差集、并集处理
    查看>>
    Openlayers高级交互(17/20):通过坐标显示多边形,计算出最大幅宽
    查看>>
    Openlayers高级交互(19/20): 地图上点击某处,列表中显示对应位置
    查看>>
    Openlayers高级交互(8/20):选取feature,平移feature
    查看>>
    openlayers:圆孔相机根据卫星经度、纬度、高度、半径比例推算绘制地面的拍摄的区域
    查看>>
    OpenLDAP(2.4.3x)服务器搭建及配置说明
    查看>>
    OpenLDAP编译安装及配置
    查看>>
    OpenMCU(一):STM32F407 FreeRTOS移植
    查看>>
    OpenMCU(三):STM32F103 FreeRTOS移植
    查看>>
    OpenMCU(二):GD32E23xx FreeRTOS移植
    查看>>
    OpenMCU(五):STM32F103时钟树初始化分析
    查看>>
    OpenMetadata 命令执行漏洞复现(CVE-2024-28255)
    查看>>