并发编程学习总结(七) :java中synchronized关键字使用详解(1)
来源:互联网 发布:mysql 函数 跳出循环 编辑:程序博客网 时间:2024/05/20 14:26
上一篇中学习了显示锁ReentrantLock和其条件对象Condition的使用,下面小小的总结一下:
(1) 锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码片段
(2) 锁可以管理试图进入被保护代码片段的线程
(3) 锁可以拥有一个或多个相关的条件对象
(4) 每个条件对象管理那些已经获得了锁,但还需要满足额外条件才能运行的线程
Lock和Condition接口为程序设计人员提供了高度的锁控制。实际上大多数情况下我们可以使用java的另一种锁机制。从jdk1.0开始,java 中每一个对象都有一个内部锁,每一个类都有一个类锁,如果一个方法用synchronized关键字声明,那么该方法称为“同步方法”,那么进入到该方法的线程将获得这个对象的锁,在该线程调用“同步方法”结束之前,其他试图调用该“同步方法”的线程将会阻塞。
同步方法的使用结构一般如下:
public synchronized void methodName() {// method body}
这种结构等价于使用显示锁的如下结构:
private ReentrantLock lock = new ReentrantLock();public void methodName() {lock.lock();try {// method body} finally {lock.unlock();}}
可以看到 使用synchronized关键字比使用内部锁ReentrantLock 要简洁的多,但是要理解同步方法的使用,你必须了解java的每一个对象都有一个内部锁,并且这个内部锁只用一个相关条件。由锁来管理那些试图进入同步方法的线程,由条件对象管理那些调用了条件对象wait() 方法的线程。
实际上synchronized关键字修饰的方法在多线程中有时会大大影响执行效率,比如当用synchronized关键字修饰Thread的run()方法时,此线程就无法调用本类中同样被synchronized关键字修饰的方法。此时我们应该减小加锁的粒度。
解决以上问题我们可以采用同步代码块的方式来使用synchronized关键字。使用结构如下:
public void methodName() {// codesynchronized(this) {// code}// code }
(1)synchronized关键字加锁
public class SynchronizedTest1 {// 使用synchronized关键字修饰的同步方法public synchronized void printNum() {for(int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}public static void main(String[] args) {// TODO Auto-generated method stubfinal SynchronizedTest1 test = new SynchronizedTest1();Thread t1 = new Thread(new Runnable() {public void run() {test.printNum();}},"A");Thread t2 = new Thread(new Runnable() {public void run() {test.printNum();}},"B");t1.start();t2.start();}}
上述代码中线程A和线程B同时运行printNum()方法,若线程A首先进入同步方法,则线程A获得当前对象的锁,当线程A结束之前时间片到时,此时线程B开始调用同步方法,由于线程A未释放获得的锁,那么线程B即进入阻塞状态。这样就保证了线程A和线程B同步输出。
(2)synchronized关键字获得的锁也是可重入锁
public class ParentSynchronized {//父类同步方法public synchronized void parentMethod() {System.out.println("parent invoke");}}public class ChildrenSynchronized extends ParentSynchronized{// 子类同步方法 public synchronized void childrenMethod() {System.out.println("children invoke");parentMethod();}public static void main(String[] args) {// TODO Auto-generated method stubfinal ChildrenSynchronized cs = new ChildrenSynchronized();Thread t = new Thread(new Runnable() {public void run() {cs.childrenMethod();}});t.start();}}
children invokeparent invoke
(3)synchronized关键字修饰类的静态方法
public class SynchronizedTest2 {// synchronized关键字修饰静态的方法 同步方法public synchronized static void printNum1(){ for(int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}// synchronized关键字使用类锁 同步代码块public static void printNum2(){ synchronized(SynchronizedTest2.class) {for(int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}}// synchronized关键字修饰 同步方法 这里使用的是对象锁public synchronized void printNum3(){ for(int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}public static void main(String[] args) {// TODO Auto-generated method stubfinal SynchronizedTest2 test = new SynchronizedTest2();Thread t1 = new Thread(new Runnable() {public void run() {SynchronizedTest2.printNum1();}},"A");Thread t2 = new Thread(new Runnable() {public void run() {SynchronizedTest2.printNum2();}},"B");Thread t3 = new Thread(new Runnable() {public void run() {test.printNum3();}},"C");t1.start();t2.start();t3.start();}}
以上代码中 静态方法printNum1() 和 printNum2() 使用的都是类锁,方法printNum3()使用的是当前对象的锁。
我们开了三个线程A,B,C分别运行printNum1(),printNum2(),printNum3()方法 从结果中我们可以看到 线程A和线程B是始终同步的,线程C和线程A,B之间没有同步关系
输出的一种结果如下:
- 并发编程学习总结(七) :java中synchronized关键字使用详解(1)
- 并发编程学习总结(八) :java中synchronized关键字使用详解 对象锁的相关条件的使用(2)
- java并发编程---synchronized关键字
- synchronized关键字详解 --Java并发编程的艺术
- java并发编程synchronized、volatile关键字及ReentrantLock类总结
- Java并发编程之七:使用synchronized获取互斥锁
- java并发编程学习6--同步--synchronized关键字
- java并发编程 (一)synchronized关键字的使用
- Java 并发编程中使用 ReentrantLock 替代 synchronized 关键字原语
- Java 并发编程中使用 ReentrantLock 替代 synchronized 关键字原语
- java并发编程学习之synchronized学习总结
- Java并发编程:synchronized关键字解析
- Java 多线程并发编程之 Synchronized 关键字
- Java 多线程并发编程之 Synchronized 关键字
- Java并发编程之同步关键字synchronized
- Java 多线程并发编程之 Synchronized 关键字
- 浅谈Java并发编程系列(七) ——— 深入解析synchronized关键字
- java中synchronized关键字详解
- ogg同步表结构不一致
- 统计汉字长度2个英文字符=1个中文
- H264--语法及结构--2
- PCA (主成分分析)详解
- C++序列式容器vector,deque,list
- 并发编程学习总结(七) :java中synchronized关键字使用详解(1)
- 【阅读】《黑客与画家》系列05-时间(节选)
- H264--编码原理以及I帧B帧P帧--1
- 数据库连接池的工作原理
- 如何有效提升Unity Gear VR游戏性能
- 从源码角度解析Java集合框架
- 欢迎使用CSDN-markdown编辑器
- H.264RTP封包原理
- 【XSHELL】xshell快捷键配置