synchronized关键字
关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性。
锁的对象是什么
对不熟悉多线程原理的人来说,很容易误解 synchronized 关键字:它通常加在所有的静态成员函数和非静态成员函数的前面,表面 看好像是“函数之间的互斥”,其实不是。synchronized关键字其实 是“给某个对象加了把锁”,这个锁究竟加在了什么对象上面?如下 面的代码所示,给函数f1()、f2()加上synchronized关键字。
1 2 3 4 5 6 7 8 | class A { public synchronized void f1() { log.info( "f11" ); } public static synchronized void f2() { log.info( "f2" ); } } |
等价于如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 | class A { public void f1() { synchronized ( this ) { log.info( "f1" ); } } public static void f2() { synchronized (A. class ) { log.info( "f2" ); } } } |
对于非静态成员函数,锁其实是加在对象a上面的;对于静态成员 函数,锁是加在A.class上面的。当然,class本身也是对象。
这间接回答了关于 synchronized 的常见问题:一个静态成员函 数和一个非静态成员函数,都加了synchronized关键字,分别被两个 线程调用,它们是否互斥?很显然,因为是两把不同的锁,所以不会 互斥。
synchronized同步的对象可以是任意对象,任意对象都有一个锁和等待队列,或者说,任何对象都可以作为锁对象。比如,f1()的等价代码还可以是。
1 2 3 4 5 6 7 8 | class A { private Object lock = new Object(); public void f1() { synchronized (lock) { log.info( "f1" ); } } } |
锁的本质是什么
无论使用什么编程语言,只要是多线程的,就一定会涉及锁。既 然锁如此常见,那么锁的本质到底是什么呢?
如图1-2所示,多个线程要访问同一个资源。线程就是一段段运行 的代码;资源就是一个变量、一个对象或一个文件等;而锁就是要实 现线程对资源的访问控制,保证同一时间只能有一个线程去访问某一 个资源。打个比方,线程就是一个个游客,资源就是一个待参观的房 子。这个房子同一时间只允许一个游客进去参观,当一个人出来后下 一个人才能进去。而锁,就是这个房子门口的守卫。
从程序角度来看,锁其实就是一个“对象”,这个对象要完成以 下几件事情:
(1)这个对象内部得有一个标志位(state变量),记录自己有 没有被某个线程占用(也就是记录当前有没有游客已经进入了房 子)。最简单的情况是这个state有0、1两个取值,0表示没有线程占 用这个锁,1表示有某个线程占用了这个锁。
(2)如果这个对象被某个线程占用,它得记录这个线程的thread ID,知道自己是被哪个线程占用了(也就是记录现在是谁在房子里 面)。
(3)这个对象还得维护一个thread id list,记录其他所有阻塞 的、等待拿这个锁的线程(也就是记录所有在外边等待的游客)。在 当前线程释放锁之后(也就是把state从1改回0),从这个thread id list里面取一个线程唤醒。
既然锁是一个“对象”,要访问的共享资源本身也是一个对象, 例如前面的对象 a,这两个对象可以合成一个对象。代码就变成synch ronized(this){…},我们要访问的共享资源是对象a,锁也是加在 对象a上面的。当然,也可以另外新建一个对象,代码变成synchroniz ed(obj1){…}。这个时候,访问的共享资源是对象a,而锁是加在新 建的对象obj1上面的。
资源和锁合二为一,使得在Java里面,synchronized关键字可以 加在任何对象的成员上面。这意味着,这个对象既是共享资源,同时 也具备“锁”的功能!
下面来看 Java 是如何做到让任何一个对象都具备“锁”的功能 的,这也就是 synchronized的实现原理。
synchronized实现原理
答案在Java的对象头里。在对象头里,有一块数据叫Mark Word。 在64位机器上,Mark Word是8字节(64位)的,这64位中有2个重要字 段:锁标志位和占用该锁的thread ID。因为不同版本的JVM实现,对 象头的数据结构会有各种差异
参考: Java并发实现原理:JDK源码剖析 1.3 synchronized关键字
Java编程的逻辑 15.2 理解synchronized
Java并发编程的艺术 4.3.1 volatile和synchronized关键字
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律