多线程三大特性:多线程
可见性、原子性、有序性ide
synchronize的特性:spa
一、同一时刻只有一个线程访问临界资源线程
二、其它未获取到锁执行权的线程必须排队等待code
三、保证共享资源的原子性、可见性和有序性对象
四、进入synchronized范围内自动加锁,synchronized做用域外锁自动消除,即便异常也会释放锁blog
synchronize加锁的方式:资源
-
对于普通同步方法,锁是当前实例对象。作用域
-
对于静态同步方法,锁是当前类的Class对象。同步
-
对于同步方法块,锁是Synchonized括号里配置的对象。
经过具体的例子来看一下
首先是普通方法:
class NoSyncTest { public void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } } private void noSyncTest() { final NoSyncTest test = new NoSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test.method2(); } }); thread1.start(); thread2.start(); }
这是一个没有任何同步的方法,NoSyncTest这个类有两个方法method1和method2,分别执行睡3s和0.5s的动做,而后再两个线程中分别调用这个类的实例test的两个方法,看一下结果:
能够看到method2和method1同时执行,method2由于sleep的时间短因此先结束。
再看一下普通方法同步:
class MethodSyncTest { public synchronized void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public synchronized void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } } private void MethodSyncTest() { final MethodSyncTest test = new MethodSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test.method2(); } }); thread1.start(); thread2.start();
synchronize修饰的method1和method2,其余不变,看一下结果:
method1先执行而后3s以后结束了method2才开始执行。(注意这个地方不能new 不一样的对象来调用方法,由于修饰普通方法本质是对对象的同步加锁。)
看一下第三种静态同步方法:
static class StaticMethodSyncTest { public static synchronized void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public static synchronized void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } public static synchronized void method3() { Log.i("sync", "method 3 start"); try { Log.i("sync", "method 3 execute"); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 3 end"); } } private void StaticMethodSyncTest() { final StaticMethodSyncTest test1 = new StaticMethodSyncTest(); final StaticMethodSyncTest test2 = new StaticMethodSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test1.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test2.method2(); } }); Thread thread3 = new Thread(new Runnable() { @Override public void run() { StaticMethodSyncTest.method3(); } }); thread1.start(); thread2.start(); thread3.start(); }
static修饰方法至关于这个方法是类方法,能够直接经过类名.方法名调用。咱们在这new出了test1和test2两个对象分别调用method1和method2,以及经过类名.方法名调用method3,看一下结果
method一、method二、method3顺序执行。(同步静态方法的本质是锁的当前类)