synchronized,是Java语言的关键字,读['siŋkrənaizd],当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多只有一个线程执行该段代码。编程
线程的同步是为了防止多个线程访问一个数据对象时,对数据形成的破坏。为确保共享变量不会出现并发问题,一般会对修改共享变量的代码块用synchronized
加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题。因此须要紧紧记住“共享”这两个字,只有共享资源的读写访问才须要同步化,若是不是共享资源,那么就没有同步的必要。安全
修饰实例方法 > 多个线程访问同一个实例的加锁方法时,会出现锁的竞争多线程
修饰静态方法 > 多个线程访问类的加锁方法时,会出现锁的竞争并发
修饰代码块 > 多线程访问到同一个代码块时,会出现竞争的问题ide
synchronized能够用来修饰方法或代码块,咱们能够把获取的同步锁归为如下3种:学习
对这3种不一样的锁,使用相互之间不受影响,对于同一种锁,会出现锁的竞态条件。测试
对于1.实例对象锁的使用:this
对于2.类对象锁的使用:spa
对于3.同步块非当前实例对象锁的使用:.net
3.测试case代码
package com.test.synchroniz; public class Service { public Service(){ System.out.println("当前线程:" + Thread.currentThread().getName() + " 构造方法"); } static{ System.out.println("当前线程:" + Thread.currentThread().getName() + " 静态代码块"); } private Object object1 = new Object(); private Object object2 = new Object(); synchronized public static void printA(){ try{ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法A"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法A"); }catch(Exception e){ System.out.println(e); } } synchronized public void printB(){ try{ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法B"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法B"); }catch(Exception e){ System.out.println(e); } } public void printC(){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法C"); try{ synchronized(object1){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + "进入方法C--synchronized{X}"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法C-synchronized{X}"); } System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法C"); }catch(Exception e){ System.out.println(e); } } public void printD(){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法D"); try{ synchronized(object2){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + "进入方法D--synchronized{X}"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法D-synchronized{X}"); } System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法D"); }catch(Exception e){ System.out.println(e); } } public void printE(){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法E"); try{ synchronized(this){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法E--synchronized{this}"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法E-synchronized{this}"); } System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法E"); }catch(Exception e){ System.out.println(e); } } public static void printF(){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法E"); try{ synchronized(Service.class){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法F--synchronized{class}"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法F-synchronized{class}"); } System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法F"); }catch(Exception e){ System.out.println(e); } } public void printG(){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法G"); try{ synchronized(Service.class){ System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 进入方法G--synchronized{class}"); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法G-synchronized{class}"); } System.out.println("当前线程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法G"); }catch(Exception e){ System.out.println(e); } } }
package com.test.synchroniz; /** * 0.synchronized同步方法、synchronized静态同步方法分别是用到的是实例锁,类锁,一个线程获取到synchronized同步方法的锁时, * 另外一线程依然能够进入synchronized静态同步方法(实例锁,类锁二者不一样,相互不影响 * ) * 1.synchronized同步方法,synchronized(this)都是对象锁,对于其余线程调用synchronized同步方法,synchronized(this)呈阻塞状态 </br> * 2.同一时间同一线程只有一个线程获取对象锁执行 </br> * * 1.synchronized(非this)对象锁,对于非this若是是同一对象,两个线程同时只有一个能够获取该锁 </br> * 2.对象锁(synchronized同步方法 或 synchronized(this))、synchronized(非this)对象锁 两个线程同时执行,均可得到各自的锁 </br> * * 1.synchronized修饰static方法与synchronized(X.class)做用同样 * * @author fugaoyang * */ public class TestRun { public static void main(String[] args) throws Exception { Service service = new Service(); Thread threadA = new Thread("A"){ @Override public void run(){ service.printA(); } }; Thread threadB = new Thread("B"){ @Override public void run(){ service.printB(); } }; Thread threadC = new Thread("C"){ @Override public void run(){ service.printC(); } }; Thread threadD = new Thread("D"){ @Override public void run(){ service.printD(); } }; Thread threadE = new Thread("E"){ @Override public void run(){ service.printE(); } }; Thread threadF = new Thread("F"){ @Override public void run(){ service.printF(); } }; Thread threadG = new Thread("G"){ @Override public void run(){ service.printG(); } }; threadA.start(); //threadB.start(); //threadC.start(); //threadD.start(); //threadE.start(); threadF.start(); threadG.start(); threadA.join(); threadF.join(); threadG.join(); } }