注:java
当一个线程执行的代码出现异常时,其所持有的锁会自动释放并发
同步不具备继承性异步
不在synchronized块中就是一部执行,在synchronized中就是同步执行ide
和synchronized方法同样,synchronized(this)代码块也是锁定当前对象的学习
1. 同步的弊端this
public class CommonUtils { public static long startTime1; public static long endTime1; public static long startTime2; public static long endTime2; }
public class DemeritOfSynchronized { private String username; private String password; public synchronized void test() { try{ System.out.println("begin the test"); Thread.sleep(3000); username = "username is " + Thread.currentThread().getName(); password = "password is " + System.currentTimeMillis(); System.out.println(username); System.out.println(password); System.out.println("end the test"); }catch (Exception e){ e.printStackTrace(); } } }
public class FirstThread extends Thread { private DemeritOfSynchronized demeritOfSynchronized; public FirstThread(DemeritOfSynchronized demeritOfSynchronized) { super(); this.demeritOfSynchronized = demeritOfSynchronized; } @Override public void run() { super.run(); CommonUtils.startTime1 = System.currentTimeMillis(); demeritOfSynchronized.test(); CommonUtils.endTime1 = System.currentTimeMillis(); } }
public class SecondThread extends Thread { private DemeritOfSynchronized demeritOfSynchronized; public SecondThread(DemeritOfSynchronized demeritOfSynchronized) { super(); this.demeritOfSynchronized = demeritOfSynchronized; } @Override public void run() { super.run(); CommonUtils.startTime2 = System.currentTimeMillis(); demeritOfSynchronized.test(); CommonUtils.endTime2 = System.currentTimeMillis(); } }
public class Run { public static void main(String[] args) { DemeritOfSynchronized demeritOfSynchronized = new DemeritOfSynchronized(); FirstThread firstThread = new FirstThread(demeritOfSynchronized); firstThread.start(); SecondThread secondThread = new SecondThread(demeritOfSynchronized); secondThread.start(); try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } long beginTime = CommonUtils.startTime1; if (CommonUtils.startTime2 < CommonUtils.startTime1) { beginTime = CommonUtils.startTime2; } long endTime = CommonUtils.endTime2; if (CommonUtils.endTime1 > CommonUtils.endTime2) { endTime = CommonUtils.endTime1; } System.out.println("spend time " + (endTime - beginTime) / 1000); } }
运行结果:线程
2. 同步代码块的使用对象
当两个并发线程访问同一个对象的object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行名一个线程必须等待当前线程执行完这个代码块以后才能执行改代码块.继承
public class ServiceMethod { public void ServiceMethod() { try { synchronized (this){ System.out.println("begin time = " + System.currentTimeMillis()); Thread.sleep(2222); System.out.println("end time = " + System.currentTimeMillis()); } }catch (Exception e){ e.printStackTrace(); } } }
public class FirstThread extends Thread { private ServiceMethod serviceMethod; public FirstThread(ServiceMethod serviceMethod){ super(); this.serviceMethod = serviceMethod; } @Override public void run(){ super.run(); serviceMethod.ServiceMethod(); } }
public class SecondThread extends Thread { private ServiceMethod serviceMethod; public SecondThread(ServiceMethod serviceMethod){ super(); this.serviceMethod = serviceMethod; } @Override public void run(){ super.run(); serviceMethod.ServiceMethod(); } }
public class Run { public static void main(String[] args){ ServiceMethod serviceMethod = new ServiceMethod(); FirstThread firstThread = new FirstThread(serviceMethod); firstThread.start(); SecondThread secondThread = new SecondThread(serviceMethod); secondThread.start(); } }
运行结果:get
3.用同步代码块解决同步方法的弊端
将1中的DemeritOfSynchronized方法代码修改成
public class DemeritOfSynchronized { private String username; private String password; public void test() { try{ System.out.println("begin the test"); Thread.sleep(3000); synchronized (this){ username = "username is " + Thread.currentThread().getName(); password = "password is " + System.currentTimeMillis(); } System.out.println(username); System.out.println(password); System.out.println("end the test"); }catch (Exception e){ e.printStackTrace(); } } }
运行结果:
4.synchronized代码块之间的同步性
在使用synchronized(this)代码块时须要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其余线程对同一个object对象中全部其余synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的对象监视器是一个.
public class SynchronizedCodes { public void SynchronizedCodes() { try { synchronized (this) { System.out.println("A begin time = " + System.currentTimeMillis()); Thread.sleep(2000); System.out.println("A end time = " + System.currentTimeMillis()); } } catch (Exception e) { e.printStackTrace(); } } public void SynchronizedCodesB() { synchronized (this) { System.out.println("B begin time = " + System.currentTimeMillis()); System.out.println("B end time = " + System.currentTimeMillis()); } } }
public class FirstThread extends Thread{ SynchronizedCodes synchronizedCodes = new SynchronizedCodes(); public FirstThread(SynchronizedCodes synchronizedCodes){ super(); this.synchronizedCodes = synchronizedCodes; } @Override public void run(){ super.run(); synchronizedCodes.SynchronizedCodes(); } }
public class SecondThread extends Thread{ SynchronizedCodes synchronizedCodes = new SynchronizedCodes(); public SecondThread(SynchronizedCodes synchronizedCodes){ super(); this.synchronizedCodes = synchronizedCodes; } @Override public void run(){ super.run(); synchronizedCodes.SynchronizedCodesB(); } }
public class Run { public static void main(String[] args){ SynchronizedCodes synchronizedCodes = new SynchronizedCodes(); FirstThread firstThread = new FirstThread(synchronizedCodes); firstThread.start(); SecondThread secondThread = new SecondThread(synchronizedCodes); secondThread.start(); } }
运行结果:
5. 将任意对象做为对象监视器
多个线程调用同一个对象中的不一样名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的.
1) synchronized同步方法
①对其余synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态.
②同一时间只有一个线程能够执行synchronized同步方法中的代码.
2) synchronized(this)同步代码块
①对其余synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态.
②同一时间只有一个线程能够执行synchronized(this)同步代码块中的代码
在前面的学习中,使用synchronized(this)格式来同步代码块,其实java还支持对任意对象做为对象监视器来实现同步的功能,这个任意对象大多数是实例变量及方法的参数,使用格式为synchronized(非this对象).
根据前面对synchronized(this)同步代码块的做用总结可知,synchronized(非this对象)格式的做用只有1种:synchronized(非this对象x同步代码块).
1)在多个线程持用对象监视器为同一个对象的前提下,同一时间只有一个线程能够执行synchronized(非this对象x)同步代码块中的代码.
2)当持有对象监视器为同一个对象的前提下,同一时间只有一个线程能够执行synchronized(非this对象x)同步代码块中的代码.
public class SynchronizedByAnyString { private String username; private String password; private String anyString = new String(); public void setUsernamAndPassword(String user, String pswd) { try { synchronized (anyString) { System.out.println("The Thread is " + Thread.currentThread().getName() + " enter time is " + System.currentTimeMillis()); username = user; Thread.sleep(2000); password = pswd; System.out.println("The Thread is " + Thread.currentThread().getName() + " leave time is " + System.currentTimeMillis()); } } catch (Exception e) { e.printStackTrace(); } } }
public class FirstThread extends Thread{ SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString(); public FirstThread(SynchronizedByAnyString synchronizedByAnyString){ super(); this.synchronizedByAnyString = synchronizedByAnyString; } @Override public void run(){ super.run(); synchronizedByAnyString.setUsernamAndPassword("scymore","scymorePassword"); } }
public class SecondThread extends Thread{ SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString(); public SecondThread(SynchronizedByAnyString synchronizedByAnyString){ super(); this.synchronizedByAnyString = synchronizedByAnyString; } @Override public void run(){ super.run(); synchronizedByAnyString.setUsernamAndPassword("b","bbbb"); } }
public class Run { public static void main(String[] args){ SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString(); FirstThread firstThread = new FirstThread(synchronizedByAnyString); firstThread.setName("firstThread"); firstThread.start(); SecondThread secondThread = new SecondThread(synchronizedByAnyString); secondThread.setName("secondThread"); secondThread.start(); } }
运行结果:
锁非this对象具备必定的优势:若是在一个类中有不少个synchronized方法,这是虽然能实现同步,但会受到阻塞,因此影响运行效率;但若是使用同步代码块锁非this对象,则synchronized(非this)代码块中的程序与同步方法是异步的,不与其余锁this同步方法争抢this锁,则可大大提升运行效率.