第三章:synchronized关键字

本文详细介绍了Java中synchronized的三种使用方式:实例方法、静态方法和同步代码块,探讨了其内存语义、可重入性,并分析了指令重排的影响,帮助读者全面掌握synchronized的使用和原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要讲解synchronized的应⽤⽅式和内存语义。

前⾔

看这篇⽂章前,建议⼤家先看我前⾯的⽂章《Java并发编程系列1-基础知识》,否则⾥⾯的相关知识看不懂,特别 是并发编程相关的可⻅性、有序性,以及内存模型JMM等。

在Java中,关键字synchronized可以保证在同⼀个时刻,只有⼀个线程可以执⾏某个⽅法或者某个代码块(主要是 对⽅法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外⼀个重要的作⽤, synchronized可保证⼀个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可⻅性,完全可以替代 Volatile功能)。

一、synchronized的三种应⽤⽅式

synchronized关键字最主要有以下3种应⽤⽅式,下⾯分别介绍:

  • 修饰实例⽅法,作⽤于当前实例加锁,进⼊同步代码前要获得当前实例的锁;
  • 修饰静态⽅法,作⽤于当前类对象加锁,进⼊同步代码前要获得当前类对象的锁;
  • 修饰代码块,指定加锁对象,对给定对象加锁,进⼊同步代码库前要获得给定对象的锁。

1.1 synchronized作⽤于实例⽅法

所谓的实例对象锁就是⽤synchronized修饰实例对象中的实例⽅法,注意是实例⽅法不包括静态⽅法,如下:

public class AccountingSync implements Runnable {
        //共享资源(临界资源)
        static int i = 0;
        // synchronized 修饰实例⽅法
        public synchronized void increase() {
            i ++;
        }
        @Override
        public void run() {
            for(int j=0;j<1000000;j++){
                increase();
            }
        }
        public static void main(String args[]) throws InterruptedException {
            AccountingSync instance = new AccountingSync();
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println("static, i output:" + i);
        }
    }
 /**
 * 输出结果:
 * static, i output:2000000
 */

如果在函数increase()前不加synchronized,因为i++不具备原⼦性,所以最终结果会⼩于2000000,具体分析可以 参考⽂章《Java并发编程系列2-volatile》。下⾯这点⾮常重要:

⼀个对象只有⼀把锁,当⼀个线程获取了该对象的锁之后,其他线程⽆法获取该对象的锁,所以⽆法访问该 对象的其他synchronized实例⽅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟码神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值