Java中同一个类中不同的synchronized办法不能够并发执行

多个线程拜访同一个类的synchronized办法时, 都是串行执行的 ! 就算有多个cpu也不例外 !
synchronized办法应用了类java的内置锁, 即锁住的是办法所属对象自身. 同一个锁某个时刻只能被一个执行线程所获取, 因而其余线程都得期待锁的开释.
因而就算你有多余的cpu能够执行, 然而你没有锁, 所以你还是不能进入synchronized办法执行, CPU因而而闲暇.
如果某个线程长期持有一个竞争强烈的锁, 那么将导致其余线程都因期待所的开释而被挂起, 从而导致CPU无奈失去利用, 零碎吞吐量低下. 因而要尽量避免某个线程对锁的长期占有 !

验证代码

public class SyncMethod {     public synchronized void syncMethod2() {        try {            System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 曾经获取内置锁`SyncMethod.this`)");            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 行将开释内置锁`SyncMethod.this`)");    }     public synchronized void syncMethod1() {        System.out.println("######################## (syncMethod1, 曾经获取内置锁`SyncMethod.this`, 并行将退出)");    }      static class Thread1 extends Thread {        SyncMethod syncMethod;         public Thread1(SyncMethod syncMethod) {            this.syncMethod = syncMethod;        }         @Override        public void run() {            syncMethod.syncMethod2();        }    }     static class Thread2 extends Thread {        SyncMethod syncMethod;         public Thread2(SyncMethod syncMethod) {            this.syncMethod = syncMethod;        }         @Override        public void run() {            System.out.println("Thread2 running ...");            syncMethod.syncMethod1();        }    }     public static void main(String[] args) throws InterruptedException {        SyncMethod syncMethod = new SyncMethod();        Thread1 thread1 = new Thread1(syncMethod);        Thread2 thread2 = new Thread2(syncMethod);         thread1.start();    //先执行, 以便抢占锁        Thread.sleep(500); //放弃cpu, 让thread1执行, 以便获的锁         thread2.start(); //在syncMethod1()办法取得锁时, 看看syncMethod2()办法是否执行         /*        是否并发执行同一个对象不同的synchronized办法, 即看看是否同时进入一个对象synchronized办法块        1. 创立一个有两个synchronized办法的对象`syncMethod`        2. 先启动一个线程(Thread1), 并让其进入syncMethod对象的sychronized办法(syncMethod1)内, 并使其停在synchronized办法内        3. 再启动一个线程(Thread2), 并执行syncMethod对象的一个synchronized办法(syncMethod2), 看看是否进入此办法内        输入如下:         @@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 曾经获取内置锁`SyncMethod.this`)        Thread2 running ...        @@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 行将开释内置锁`SyncMethod.this`)        ######################## (syncMethod1, 曾经获取内置锁`SyncMethod.this`, 并行将退出)        后果剖析:             察看显示, 在输入`Thread2 running ...`后会暂停数秒(Thread2无奈取得所而被挂起, 因为锁曾经被Thread1持有).            如果不同线程能够同时拜访同一个对象不同synchronized办法的话,             在有足够cpu工夫片时(Thread1在调用syncMethod1时应用Thread.sleep放弃了cpu),             Thread2调用的syncMethod2办法应该马上执行, 也就是syncMethod2办法中的语句在`Thread2 running ...`语句输入后马上输入,             而不是期待数秒才输入 (应为此时没有其余线程跟Thread2竞争cpu, 况且当初的电脑都不只一个cpu),             因而得出结论: "不同线程不能同时执行一个对象的不同synchronized办法"            其实此论断是不言而喻的, 原理后面曾经说明, 此处不再赘述.        */     }}

上面是一些对于应用锁的一些倡议:

①为了防止对锁的竞争, 你能够应用锁合成, 锁分段以及缩小线程持有锁的工夫

②如果上诉程序中的syncMethod1和syncMethod2办法是两个不相干的办法(申请的资源不存在关系),那么这两个办法能够别离应用两个不同的锁,革新之后Thread1和Thread2就不会产生因为锁竞争而挂起的状况了。革新后的SyncMethod类如下:

锁定两个不同的Object对象(lock1、lock2)

public class SyncMethod {    private Object lock1 = new Object();    private Object lock2 = new Object();     public void syncMethod2() {        synchronized (lock1) {            try {                System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 曾经获取内置锁`SyncMethod.this`)");                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 行将开释内置锁`SyncMethod.this`)");        }    }     public void syncMethod1() {        synchronized (lock2) {            System.out.println("######################## (syncMethod1, 曾经获取内置锁`SyncMethod.this`, 并行将退出)");        }    }}

当然, 如果syncMethod1中耗时操作与锁定的资源无关, 那么也能够将耗时操作移出同步块. 在上述革新的根底上对syncMethod1的进一步革新如下:

public void syncMethod2() {    synchronized (lock1) {        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 曾经获取内置锁`SyncMethod.this`)");        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 行将开释内置锁`SyncMethod.this`)");    }      //将耗时操作移出同步块    try {        Thread.sleep(5000);//与同步应用的资源无关的耗时操作    } catch (InterruptedException e) {        e.printStackTrace();    }}