【Java Tip】(四) synchronized关键字
2016-12-08 21:25
274 查看
本文作者Nemo, http://blog.csdn.net/nemo__
synchronized方法控制对类成员变量的访问:每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁才能执行,synchronized关键字可以修饰方法或代码块。
如果一个类有多个synchronized方法,某一时刻某个线程已经进入到了该类的对象obj的某个synchronized方法时,那么在该方法没有执行完毕前,其他线程是无法访问该对象obj的任何synchronized方法的。
Java中的每个对象都有一个锁(lock),或者叫做监视器(monitor),当一个线程访问某个对象的synchronized方法时,将该对象上锁,其他任何线程都无法再去访问该对象的synchronized方法了(这里是指所有的同步方法,而不仅仅是同一个方法),直到之前的那个线程执行方法完毕后(或者是抛出了异常),才将该对象的锁释放掉,其他线程才有可能再去访问该对象的synchronized方法。
注意这里是给对象上锁,如果是不同的对象,则各个对象之间没有限制关系。
上例中两个不同的线程t1, t2执行同一个对象example的两个synchronized方法,会互相影响,直到一个执行再执行另一个。如果这里t2传入的是另一个example2,则执行互不影响。
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
synchronized静态方法相当于把该方法内部所有内容使用synchronized括住,参数为ClazzT.class。
被synchronized保护的数据应该是私有的;也就是同步方法控制访问的变量必须是私有,且其getter或setter方法也需要synchronized保护。
synchronized锁定的是对象,多线程看是否达到同步效果,只要看synchronized后的参数锁是否是同一个。不同的对象实例的synchronized方法是不相干扰的。synchronized的非静态方法和静态方法因为锁定的是不同的内容,因此它们之间没有同步关系,两个线程不互斥。
ClazzT.class和instance.getClass()用于作同步锁还不一样,不能用instance.getClass()来达到锁这个Class的目的。
private byte[] lock = new byte[0];零长度的byte数组对象创建起来将比任何对象都经济,查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
参考:
http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html
http://ifeve.com/java-synchronized/
http://www.jiacheo.org/blog/317
synchronized方法控制对类成员变量的访问:每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁才能执行,synchronized关键字可以修饰方法或代码块。
一、synchronized修饰方法
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。如果一个类有多个synchronized方法,某一时刻某个线程已经进入到了该类的对象obj的某个synchronized方法时,那么在该方法没有执行完毕前,其他线程是无法访问该对象obj的任何synchronized方法的。
Java中的每个对象都有一个锁(lock),或者叫做监视器(monitor),当一个线程访问某个对象的synchronized方法时,将该对象上锁,其他任何线程都无法再去访问该对象的synchronized方法了(这里是指所有的同步方法,而不仅仅是同一个方法),直到之前的那个线程执行方法完毕后(或者是抛出了异常),才将该对象的锁释放掉,其他线程才有可能再去访问该对象的synchronized方法。
注意这里是给对象上锁,如果是不同的对象,则各个对象之间没有限制关系。
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread2(example); t1.start(); t2.start(); } } class Example { public synchronized void execute() { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Hello: " + i); } } public synchronized void execute2() { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("World: " + i); } } } class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.execute(); } } class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { example.execute2(); } }
上例中两个不同的线程t1, t2执行同一个对象example的两个synchronized方法,会互相影响,直到一个执行再执行另一个。如果这里t2传入的是另一个example2,则执行互不影响。
二、synchronized修饰静态方法
如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的类所对应的Class对象。Java中,无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,它们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始。public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); //此处即便传入不同的对象,静态方法同步仍然不允许多个线程同时执行 example = new Example(); Thread t2 = new Thread2(example); t1.start(); t2.start(); } } class Example { public synchronized static void execute() { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Hello: " + i); } } public synchronized static void execute2() { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("World: " + i); } } } class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { Example.execute(); } } class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { Example.execute2(); } }
三、synchronized代码块
synchronized方法实际上等同于用一个synchronized块包住方法中的所有语句,然后在synchronized块的括号中传入this关键字。当然,如果是静态方法,需要锁定的则是class对象。synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
四、等价转换
synchronized方法等价于把该方法内部所有内容使用synchronized括住,参数为this。void synchronized method(){ //biz code } ------>>>等价于 void method(){ synchronized(this){ //biz code } }
synchronized静态方法相当于把该方法内部所有内容使用synchronized括住,参数为ClazzT.class。
class ClazzT { void synchronized static method(){ //biz code } } ------>>>相当于 class ClazzT { void method(){ synchronized(ClazzT.class){ //biz code } } }
五、总结
Java慎用方法级别的synchronized关键字;被synchronized保护的数据应该是私有的;也就是同步方法控制访问的变量必须是私有,且其getter或setter方法也需要synchronized保护。
synchronized锁定的是对象,多线程看是否达到同步效果,只要看synchronized后的参数锁是否是同一个。不同的对象实例的synchronized方法是不相干扰的。synchronized的非静态方法和静态方法因为锁定的是不同的内容,因此它们之间没有同步关系,两个线程不互斥。
ClazzT.class和instance.getClass()用于作同步锁还不一样,不能用instance.getClass()来达到锁这个Class的目的。
private byte[] lock = new byte[0];零长度的byte数组对象创建起来将比任何对象都经济,查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
参考:
http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html
http://ifeve.com/java-synchronized/
http://www.jiacheo.org/blog/317
相关文章推荐
- 搞懂java中的synchronized关键字
- java中的synchronized关键字
- java原子性以及关键字volatile、synchronized
- Java并发与synchronized关键字
- Java多线程系列--“基础篇”04之 synchronized关键字
- Java并发之synchronized关键字
- Java——多线程总结及ThreadLocal、Volatile、synchronized、Atomic四个关键字
- Java 多线程并发编程之 Synchronized 关键字
- 深入讲解java线程与synchronized关键字
- java synchronized关键字的详解
- Java同步机制总结--synchronized关键字的使用
- 关于java中的synchronized关键字的理解
- java synchronized关键字
- Java 多线程:synchronized 关键字用法(修饰类,方法,静态方法,代码块)
- Java 多线程(六) synchronized关键字详解
- java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)
- java中的synchronized关键字 用法
- Java 多线程----synchronized关键字详解
- java中的synchronized关键字