不能够!!!java
多个线程访问同一个类的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方法是两个不相干的方法(请求的资源不存在关系), 那么这两个方法能够分别使用两个不一样的锁, 改造后的SyncMethod类以下:并发
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`, 并即将退出)"); } } }
改造以后Thread1和Thread2就不会发生, 因为锁竞争而挂起的状况了.ide
固然, 若是syncMethod1中耗时操做与锁定的资源无关, 那么也能够将耗时操做移出同步块. 在上述改造的基础上对syncMethod1的进一步改造以下:this
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(); } }