重新认识synchronized(上)
synchronized在JDK5之前一直被称为重量级锁,是一个较为鸡肋的设计,而在JDK6对synchronized内在机制进行了大量显著的优化,加入了CAS,轻量级锁和偏向锁的功能,性能上已经跟ReentrantLock相差无几,而且synchronized在使用上更加简单,不易出错(避免哲学家就餐问题造成的死锁),因此如果仅仅是为了实现互斥,而不需要使用基于Lock的附加属性(中断、条件等),推荐优先使用synchronized。
synchronized用法
synchronized有同步方法和同步语句块两种形式,分锁定对象和作用域两个维度,当锁定的对象进入作用域时,互斥才会生效。一个线程访问拥有相同锁定对象时,进入作用域时必须以串行方式进行。修饰的对象有:修饰普通方法(又称为同步方法),修饰静态方法,修饰对象实例,修饰class literals(类名称字面常量)。
修饰普通方法
又称同步方法,锁定的是调用这个同步方法对象。一个线程访问实例对象中的synchronized代码块时,其他试图访问该对象synchronized修饰的区域的线程将阻塞。同一个对象共享一把锁,同一时间只能有一个synchronized区域可以获得锁,可以称为对象锁。需要注意两点:(1)作用只会在同一个实例上,(2)对象中的所有synchronized修饰的区域。例如:对于fooA对象,线程t1,t2访问methodA是互斥的,线程t1,t2分别访问methodA,methodB同样是互斥的;当访问methodA时,methodB 不可以访问,methodC可以访问。
public class Foo implements Runnable {
public static synchronized void methodA() {
//TODO
} public static synchronized void methodB() {
//TODO
} public void methodC() {
//TODO
} public static void main(String[] args) {
Foo fooA = new Foo();
Foo fooB = new Foo(); Thread t1 = new Thread(fooA, "t1");
Thread t2 = new Thread(fooB, "t2");
t1.start();
t2.start();
}
}
修饰静态方法
锁定是静态方法所属的类,此时该类共用一把锁,可以称为类锁。一个线程访问synchronized静态方法时,其他试图访问该类synchronized修饰的区域的线程都将阻塞,而非synchronized修饰的区域不会阻塞。修饰静态方法是修饰普通方法的变种版,前者锁定该类(跟对象没关系),后者指锁定当前对象。例如:线程t1,t2分别访问methodA,methodB同样是互斥的。
同步语句块
修饰对象实例的情况与修饰普通方法一致,区别在于只有线程进入同步语句块时,才是互斥的。而修饰class literals(类名称字面常量)与修饰静态方法一致。例如:methodD锁定的是当前对象,而methodE中的synchronized锁定的是Foo类的所有对象。
public class Foo {
public void methodD() {
synchronized (this) {
//TODO
}
} public void methodE() {
synchronized (Foo.class) {
//TODO
}
}
}
synchronized机制
synchronized是Java为线程间通信提供的一种方式,synchronized的这种同步机制是互斥锁机制。实现互斥的方式有:临界区(Critical Section),互斥量(Mutex),信号量(Semaphores)和事件(Event)。
synchronized是采用临界区的方式实现互斥的,通过对多线程的串行化来访问公共资源或一段代码,保证同一时刻只有一个线程能访问临界区内共享数据。如果多个线程试图同时访问临界区,其中一个线程抢占临界区后,其他试图访问该临界区的线程将会挂起,直到进入临界区的线程。举个栗子,会议室资源相对紧张,有多个团队都需要使用会议室,这时就看哪个团队的迅速了。当这个团队抢占到会议室后,就会挂起“正在会议中”的提示牌,其他需要使用会议室的人看到会等待,直到当前使用会议室的团队使用完,移走“正在会议中”的提示牌。
synchronized同时保证了可见性。互斥锁释放后,确保一个线程修改的对象状态,对其他线程是可见的,即在随后获取锁的线程中保证获得最新共享资源的状态。synchronized互斥锁是通过监视器(Monitor)实现的。
什么是监视器(Monitor)
监视器是一种同步机制。 通过获取和释放锁,保证线程间可以互斥地操作共享资源,同一时间最多只有一个线程占用监视器,即互斥(mutex);采用条件变量(Condition Variables),允许线程阻塞和等待另一个线程发送信号的方法弥补互斥锁的不足,这就是监视器的互斥和协作。
当多线程同时访问一段同步代码时,新请求的线程会首先加入到Entry Set集合中,通过竞争(compete)方式,同一时间只有一个线程可以竞争成功并获取监视器,进入The Owner。获取监视器的线程调用wait()后就会释放监视器,并进入Wait Set集合中等待满足条件时被唤醒。无论是acquire还是release都是使用原子指令如test-and-set、compare-and-set来实现自旋锁来保证对关键段的访问。java-monitor
参考
重新认识synchronized(上)的更多相关文章
- 并发和多线程-八面玲珑的synchronized
上篇<并发和多线程-说说面试常考平时少用的volatile>主要介绍的是volatile的可见性.原子性等特性,同时也通过一些实例简单与synchronized做了对比. 相比较volat ...
- synchronized的功能拓展:重入锁(读书笔记)
重入锁可以完全代替synchronized关键字.在JDK5.0的早期版本中,重入锁的性能远远好于synchronized,但是从JDK6.0开始.JDK在synchronized上做了大量的优化. ...
- 线程互斥synchronized
/** * * 线程互斥,采用synchronized关键字可以实现线程与线程之间的互斥,要注意的是在synchronized上的对象要是同一个,才可以 * 保证在同一时刻,只有一个线程可以执行syn ...
- 多线程编程学习四(Lock 的使用).
一.前言 本文要介绍使用Java5中 Lock 对象,同样也能实现同步的效果,而且在使用上更加方便.灵活,主要包括 ReentrantLock 类的使用和ReentrantReadWriteLock ...
- Java面试准备之多线程
什么叫线程安全?举例说明 多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程 ...
- Java基础知识盘点(三)- 线程篇
创建线程的方式及实现 一.继承Thread类创建线程类 1.定义Thread的子类,并重写run方法,因为该方法的方法体就是代表了线程要完成的任务,因此run方法又叫做执行体. 2.创建Thread子 ...
- JDK并发工具之同步控制
一.synchronized的功能扩展:重入锁(java.util.concurrent.locks.ReentrantLock) 重入锁可以完全替代synchronized关键字.在JDK 5.0的 ...
- 《Java并发编程的艺术》留给自己以后看的笔记
<Java并发编程的艺术>这本书特别好,和<深入了解JAVA虚拟机>有一拼,建议做java的都看看,下面全部都是复制书中的部分内容,主要目的是做个笔记,方便以后遇到问题能找到. ...
- 实验11——java线程模拟卖票
package cn.tedu.demo; /** * @author 赵瑞鑫 E-mail:1922250303@qq.com * @version 1.0 * @创建时间:2020年7月31日 下 ...
- 《Java并发编程的艺术》笔记
第1章 并发编程的挑战 1.1 上下文切换 CPU通过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换. 减少上下文切换的方法有4种:无锁并发编程.CAS算法.使用最少线程.使 ...
随机推荐
- EntityFramework 学习 一 Validate Entity
可以为实体实现自定义验证,重写DBContext中的个ValidateEntity方法 protected override System.Data.Entity.Validation.DbEntit ...
- java基础10(IO流)-字节流
IO流 输入与输出[参照物是程序] 如果从键盘.文件.网络甚至是另一个进程(程序或系统)将数据读入到程序或系统中,称为输入 如果是将程序或系统中的数据写到屏幕.硬件上的文件.网络上的另一端或者是一个进 ...
- scrapy的操作
- utf-8编码汉字转换成对于的16进制 10进制对于的值
http://www.mytju.com/classcode/tools/encode_utf8.asp
- [eBook]Inside Microsoft Dynamics AX 2012 R3发布
最近一本关于Microsoft Dynamics AX 2012开发的书<Inside Microsoft Dynamics AX 2012 R3> 发布. Book Descriptio ...
- Mybatis 别名机制,自动扫描 数据的增删改
mybatis别名机制: 在mybatis.xml文件中的<configuration></configuration>标签中间加入属性<typeAliases>& ...
- linux内嵌汇编语言
http://blog.chinaunix.net/uid-21254310-id-1828921.html http://www.cnblogs.com/lxgeek/archive/2011/01 ...
- linux下的制作静态库并使用它
静态库所要用的源文件 文件 fred.c #include <stdio.h> void fred(int argc) { printf("void fred(i ...
- bzoj 4710 分特产
有 $n$ 个人,$m$ 种物品,每种物品有 $a_i$ 个,求每个人至少分到一个的方案数 $n,m,a_i \leq 2000$ sol: 比上一个题简单一点 还是考虑容斥 每个人至少分到一个 = ...
- LeetCode Minimum Index Sum of Two Lists
原题链接在这里:https://leetcode.com/problems/minimum-index-sum-of-two-lists/description/ 题目: Suppose Andy a ...