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

    你可能感兴趣的文章
    mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
    查看>>
    MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
    查看>>
    MYSQL8.0以上忘记root密码
    查看>>
    Mysql8.0以上重置初始密码的方法
    查看>>
    mysql8.0新特性-自增变量的持久化
    查看>>
    Mysql8.0注意url变更写法
    查看>>
    Mysql8.0的特性
    查看>>
    MySQL8修改密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
    查看>>
    MySQL8修改密码的方法
    查看>>
    Mysql8在Centos上安装后忘记root密码如何重新设置
    查看>>
    Mysql8在Windows上离线安装时忘记root密码
    查看>>
    MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案
    查看>>
    mysql8的安装与卸载
    查看>>
    MySQL8,体验不一样的安装方式!
    查看>>
    MySQL: Host '127.0.0.1' is not allowed to connect to this MySQL server
    查看>>
    Mysql: 对换(替换)两条记录的同一个字段值
    查看>>
    mysql:Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘解决方法
    查看>>
    MYSQL:基础——3N范式的表结构设计
    查看>>
    MYSQL:基础——触发器
    查看>>
    Mysql:连接报错“closing inbound before receiving peer‘s close_notify”
    查看>>