synchronized 关键字
来源:互联网 发布:淘宝怎么设置快递模板 编辑:程序博客网 时间:2024/04/29 10:02
在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确保在某一时刻,方法内只允许有一个线程。
采用 synchronized 修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象都有一个 monitor (锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。
这里就使用同步机制获取互斥锁的情况,进行几点说明:
如果同一个方法内同时有两个或更多线程,则每个线程有自己的局部变量拷贝。
类的每个实例都有自己的对象级别锁。当一个线程访问实例对象中的 synchronized 同步代码块或同步方法时,该线程便获取了该实例的对象级别锁,其他线程这时如果要访问 synchronized 同步代码块或同步方法,便需要阻塞等待,直到前面的线程从同步代码块或方法中退出,释放掉了该对象级别锁。
访问同一个类的不同实例对象中的同步代码块,不存在阻塞等待获取对象锁的问题,因为它们获取的是各自实例的对象级别锁,相互之间没有影响。
持有一个对象级别锁不会阻止该线程被交换出来,也不会阻塞其他线程访问同一示例对象中的非 synchronized 代码。当一个线程 A 持有一个对象级别锁(即进入了 synchronized 修饰的代码块或方法中)时,线程也有可能被交换出去,此时线程 B 有可能获取执行该对象中代码的时间,但它只能执行非同步代码(没有用 synchronized 修饰),当执行到同步代码时,便会被阻塞,此时可能线程规划器又让 A 线程运行,A 线程继续持有对象级别锁,当 A 线程退出同步代码时(即释放了对象级别锁),如果 B 线程此时再运行,便会获得该对象级别锁,从而执行 synchronized 中的代码。
持有对象级别锁的线程会让其他线程阻塞在所有的synchronized代码外。例如,在一个类中有三个synchronized 方法 a,b,c,当线程 A 正在执行一个实例对象 M 中的方法 a 时,它便获得了该对象级别锁,那么其他的线程在执行同一实例对象(即对象 M)中的代码时,便会在所有的 synchronized 方法处阻塞,即在方法 a,b,c 处都要被阻塞,等线程 A 释放掉对象级别锁时,其他的线程才可以去执行方法 a,b 或者 c 中的代码,从而获得该对象级别锁。
使用 synchronized(obj)同步语句块,可以获取指定对象上的对象级别锁。obj 为对象的引用,如果获取了 obj 对象上的对象级别锁,在并发访问 obj 对象时时,便会在其 synchronized 代码处阻塞等待,直到获取到该 obj对象的对象级别锁。当 obj 为 this 时,便是获取当前对象的对象级别锁。
类级别锁被特定类的所有示例共享,它用于控制对 static 成员变量以及 static 方法的并发访问。具体用法与对象级别锁相似。
互斥是实现同步的一种手段,临界区、互斥量和信号量都是主要的互斥实现方式。synchronized 关键字经过编译后,会在同步块的前后分别形成 monitorenter 和 monitorexit 这两个字节码指令。根据虚拟机规范的要求,在执行 monitorenter 指令时,首先要尝试获取对象的锁,如果获得了锁,把锁的计数器加 1,相应地,在执行 monitorexit 指令时会将锁计数器减 1,当计数器为 0 时,锁便被释放了。由于 synchronized 同步块对同一个线程是可重入的,因此一个线程可以多次获得同一个对象的互斥锁,同样,要释放相应次数的该互斥锁,才能最终释放掉该锁。
- 同步代码块语法:
synchronized(受益对象){代码块}
- 同步方法同同步代码块的区别
- 1.同步方法,是通过this关键字找到当前对象,将当前对象上锁
- 2.同步代码块,可以指定任意一个对象
- 同步代码块,可以控制的更具体
Java中每个对象都有同步锁,同步方法是指进入该方法时需要获取this对象的同步锁,而同步代码块则是可以指定需要获取哪个对象的同步锁,以下代码实际上一个效果:
- 同步代码块语法:
//1.同步方法synchronized void t(){ //do something}//2.同步代码块void t(){ synchronized(this){ //do something }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
同步代码块可以用如下方式来使用:
void t(){ synchronized(lockObject){}}
- 1
- 2
- 3
- 1
- 2
- 3
其中lockObject可以为任何不为null值的对象)
参考:
http://wiki.jikexueyuan.com/project/java-concurrency/synchronized.html
http://blog.csdn.net/nyistzp/article/details/12855287
- 顶
- 0
- 踩
- 0
- 上一篇JVM 类加载器介绍及其双亲委托机制
- 下一篇多线程环境下安全使用集合 API
我的同类文章
- •Java RMI详解(入门)2016-09-12
- •Java序列化算法透析2016-09-03
- •Java NIO 总结与示例2016-08-14
- •Java 连接池的工作原理 **2016-05-13
- •Java 7之基础 - 强引用、弱引用、软引用、虚引用(总结的很好)2016-05-11
- •通过 ActiveMQ 演示如何使用 JMS API (入门)2016-05-05
- •Web开发中文乱码问题2016-09-08
- •《Java性能优化...》读书笔记2016-08-20
- •eclipse字体 osgi错误Could not find bundle: org.eclipse.equinox.console2016-06-26
- •Java阻塞队列的实现 (简洁明了)2016-05-13
- •关于finalize()方法(总结)2016-05-11
- synchronized 关键字
- synchronized关键字
- synchronized关键字
- synchronized关键字
- 关键字synchronized
- synchronized关键字
- synchronized关键字
- synchronized关键字
- synchronized关键字
- synchronized 关键字
- synchronized关键字
- synchronized关键字
- synchronized关键字
- Synchronized关键字
- Synchronized关键字
- synchronized关键字
- synchronized 关键字
- synchronized 关键字
- JAVA学习之封装
- HDU2389-Rain on your Parade(二分图匹配Hopcroft-Karp算法)
- 三天打鱼两天晒网(Android版)
- Chrome开发者工具不完全指南(一、基础功能篇)
- 设计模式学习-单例模式
- synchronized 关键字
- Python正则表达式指南
- Longest Consecutive Sequence
- Quartz2.x学习笔记(四):spring注入异常解决方法
- 周赛西北第二次周赛(感谢佳神的讲解)
- URL基础
- dg日志传输服务
- java——异常
- POJ 1321 棋盘问题 (DFS+回溯)