不可以!!!

多个线程访问同一个类的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就不会发生, 由于锁竞争而挂起的情况了.

当然, 如果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();
}
}

Java中两个线程是否可以同时访问同一个对象的两个不同的synchronized方法?的更多相关文章

  1. Java中如何创建线程

    Java中如何创建线程 两种方式:1)继承Thread类:2)实现Runnable接口. 1.继承Thread类 继承Thread类,重写run方法,在run方法中定义需要执行的任务. class M ...

  2. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  3. Java中正确终止线程的方法

    Thread类中有一个已经废弃的 stop() 方法,它可以终止线程,但由于它不管三七二十一,直接终止线程,所以被废弃了.比如,当线程被停止后还需要进行一些善后操作(如,关闭外部资源),使用这个方法就 ...

  4. 设计四个线程,当中共两个线程每次对j添加1,另外两个线程每次对j降低1。循环100次,写出程序。

    package cn.usst.DataTest6; /** * 设计四个线程,当中共两个线程每次对j添加1,另外两个线程每次对j降低1.循环100次,写出程序. * @ * */ public cl ...

  5. 设计 4 个线程,其中两个线程每次对 j 增加 1 ,另外两个线程对 j 每次减少 1 。写出程序。

    题目:设计 4 个线程,其中两个线程每次对 j 增加 1 ,另外两个线程对 j 每次减少 1 .写出程序. 代码实现 public class ThreadTest{ private int j; c ...

  6. java 多线程访问同一个对象数据保护的问题

    java 多线程同时访问统一个数据的时候,会引起一些错误,后面的线程会修改数据,而前面的线程还在使用修改前的内容, 使用 synchronized 关键字,保证代码块只能有一个线程来访问 public ...

  7. 关于Java中进程和线程的详解

    一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...

  8. Java中怎样创建线程安全的方法

    面试问题: 下面的方法是否线程安全?怎样让它成为线程安全的方法? class MyCounter { private static int counter = 0; public static int ...

  9. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

随机推荐

  1. 汉语言处理工具pyhanlp的简繁转换

      繁简转换 HanLP几乎实现了所有我们需要的繁简转换方式,并且已经封装到了HanLP中,使得我们可以轻松的使用,而分词器中已经默认支持多种繁简格式或者混合.这里我们不再做过多描述. 说明: ·Ha ...

  2. Spark Streaming 'numRecords must not be negative'问题解决

    转载自:http://blog.csdn.net/xueba207/article/details/51135423 问题描述 笔者使用spark streaming读取Kakfa中的数据,做进一步处 ...

  3. Tomcat性能调优后, 启动出现警告问题 [did not find a matching property.]

    http://blog.csdn.net/dracotianlong/article/details/8963594 Tomcat性能调优后, 启动出现警告问题 [did not find a mat ...

  4. 作业-JSP简单入门

    说明 本次作业不打分,仅作为大家自学的指导. 本次实验内容以"JSP实验参考文件"为主. 参考资料 Java教学问卷调查,有什么想说的,请尽情投票吧! 反射实验参考文件 JSP实验 ...

  5. Nodepad++ 进行数据分析操作

    查找: ^.*大师兄.*$ 替换为:(空)   如果不留空行: 查找: ^.*大师兄.*\r?\n   注意: Notepad++的[全部替换]受[方向]约束,所以如果想“向下”全部替换,要把光标放到 ...

  6. CSS之padding&margin

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. vue源码核心部分

    1.模板编译   初始化时做的:template ==parse()==>ASTtree ==generate()==>render函数  ==> mount(调用dom方法) 每次 ...

  8. sql使用实例

    将另一表中的合计值保存到指定字段,并将空值赋0 update ShopInfo set JLRunningWater =(select COALESCE(sum(v.TotalMoney),0) as ...

  9. ef join查询

    temp = temp.OrderByDescending(s => s.CreateTime).Skip((param.PageIndex - ) * param.PageSize).Take ...

  10. Java虚拟机------JVM介绍

    Java平台和语言最开始只是SUN公司在1990年12月开始研究的一个内部项目: Java的平台无关性 Java平台和语言最开始只是SUN公司在1990年12月开始研究的一个内部项目[stealth ...