在多线程访问同一个对象中的不同的synchronized方法或synchronized代码块的前提下,也就是“对象监控器”为同一个对象的时候,也就是synchronized的锁为同一把锁的时候,调用的效果就是:当前正在执行的synchronized方法或synchronized代码块的运行结果是同步的,但是对其synchronized方法或synchronized代码块来说是阻塞的。同步是因为当一个线程执行synchronized方法或代码块的时候,正常情况下,别的线程永远得不到CPU的执行机会。也就是因为别的线程永远得不到执行机会,所以其他synchronized方法和synchronized代码块没有机会被执行,造成阻塞。

其实Java还支持“任意对象”作为“对象监视器”,来实现同步的功能,这个“任意对象”大多数为实例变量或者方法形参,使用的格式为synchronized(非this对象)同步代码块。那么她的特点和synchronized(this)代码块是一样的,特点如下:在多个线程持有“对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)代码块里的代码。我写了一个小例子来证明,代码如下:

public static void main(String[] args) {

		MyService1 service = new MyService1();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
} public static class ThreadA extends Thread { private MyService1 service; public ThreadA(MyService1 service) {
super();
this.service = service;
} @Override
public void run() { super.run();
service.serviceMethodA("a", "A"); }
} public static class ThreadB extends Thread { private MyService1 service; public ThreadB(MyService1 service) {
super();
this.service = service;
} @Override
public void run() { super.run();
service.serviceMethodA("b", "B"); }
}
} class MyService1 { private String userName, userPassWord;
String s = new String(); public void serviceMethodA(String userName, String userPassWord) {
synchronized (s) { try {
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
Thread.sleep(5000);
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
} catch (InterruptedException e) { e.printStackTrace();
}
}
} }

      运行结果如下:从代码上可以看到,线程A和线程B访问的都是service这个对象,所以“对象监控器”为同一个对象,理论上,在这种情况,执行的结果应该是同步的,从控制台打印的结果来看,也确实是同步的。

那么synchronized(非this对象)有什么优点呢,我们假设在一个类中有很多synchronized修饰的方法,虽然可以实现同步,但是同时也形成了阻塞,这样就影响了运行效率,但是使用同步代码块非this锁就可以解决这个问题,因为非this锁和this锁是异步的,他们之间不会互相争夺锁,这样运行效率就提高了。下面看一个例子来证明这件事情,只需要在MyService1类里添加一个方法即可,然后线程B调用该方法。代码如下:

	public void serviceMethodB(String userName, String userPassWord) {
synchronized (this) { try {
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
Thread.sleep(5000);
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
} catch (InterruptedException e) { e.printStackTrace();
}
}
}

     运行结果如下:由于“对象监视器”不同,所以运行的结果是异步的,这个异步说的是方法serviceMethodA和方法serviceMethodB之间是异步的,交叉执行的。

上面说过了多个线程同时访问synchronized(非this对象)代码块时,呈同步效果,也就是说必须一个线程执行完释放掉锁,另一个线程才可以执行。也说过了多个线程分别访问this锁和非this锁,呈异步效果,可以提高运行效率。接下来说一说多线程访问不同的对象是什么效果,也就是使用不同的“对象监视器”。下面看一个例子,代码如下:

public static void main(String[] args) {

		MyService4 service = new MyService4();
MyObject1 object = new MyObject1();
MyObject1 object1 = new MyObject1();
//两个线程传入不同的对象
ThreadA a = new ThreadA(service, object);
a.setName("A");
ThreadB b = new ThreadB(service, object1);
b.setName("B");
a.start();
b.start();
} public static class ThreadA extends Thread { private MyService4 service;
private MyObject1 object; public ThreadA(MyService4 service, MyObject1 object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() { super.run();
service.serviceMethod(object); }
} public static class ThreadB extends Thread { private MyService4 service;
private MyObject1 object; public ThreadB(MyService4 service, MyObject1 object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() { super.run();
service.serviceMethod(object); }
}
} class MyService4 { public void serviceMethod(MyObject1 object) {
synchronized (object) { try {
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
Thread.sleep(5000);
System.out.println("线程" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
} catch (InterruptedException e) { e.printStackTrace();
}
}
} } class MyObject1 {
}

     运行结果如下:由结果可以看出来,如果使用不同的“对象监视器”,结果是异步执行的。

Java多线程之synchronized(三)的更多相关文章

  1. JAVA多线程之Synchronized关键字--对象锁的特点

    一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...

  2. JAVA多线程之Synchronized、wait、notify实例讲解

    一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...

  3. (二)java多线程之synchronized

    本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/kco198 ...

  4. Java多线程之synchronized及其优化

    Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...

  5. java 多线程之synchronized wait/notify解决买票问题

    一.Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的st ...

  6. Java多线程之synchronized详解

    目录 synchronized简介 同步的原理 对象头与锁的实现 锁的优化与升级 Monitor Record 锁的对比 synchronized简介 synchronized关键字,一般称之为&qu ...

  7. Java多线程之synchronized(四)

    前面几章都是在说synchronized用于对象锁,无论是修饰方法也好修饰代码块也好,然而关键字synchronized还可以应用到static静态方法上,如果这样写,那就是对当前的*.java文件所 ...

  8. JAVA多线程之synchronized和volatile实例讲解

    在多线程中,提到线程安全.线程同步,我们经常会想到两个关键字:volatile和synchronized,那么这两者有什么区别呢? 1. volatile修饰的变量具有可见性 volatile是变量修 ...

  9. Java多线程之synchronized和volatile

    概述 用Java来开发多线程程序变得越来越常见,虽然Java提供了并发包来简化多线程程序的编写,但是我们有必要深入研究一下,才能更好的掌握这块知识. 本文主要对Java提供的底层原语synchroni ...

随机推荐

  1. 使用mybatis查询数据,按特定顺序排序

    有如下表table_people id          name 1          dwyane 2          james 3          paul 4          bosh ...

  2. Android安装应用失败UID 和 PID

    参考:http://blog.sina.com.cn/s/blog_62ef2f140101j6q2.html 安装任意第三方的一个apk,恢复出厂设置,再次安装相同的apk,提示安装失败,通过打印L ...

  3. ubuntu-10.04的测试环境 安装测试 Coreseek开源中文检索引擎-Sphinx中文版

    主要参考文档:http://www.coreseek.cn/products-install/install_on_bsd_linux/ 一. 32位版本: coreseek安装需要预装的软件: ap ...

  4. latex 批量注释

    在LaTex中的注释有3种方法: 1. 右键单击选中要注释的文本,选择 Insert Comment ,WinEdt 就会自动给选定的行添加 % ,完成段落文本的注释: 右键单击选中已经注释的文本,选 ...

  5. 配置Raspbian 启用SPI I2C

    sudo vi /etc/modprobe.d/raspi-blacklist.conf 找到这两行 blacklist spi-bcm2708 blacklist i2c-bcm2708 注释掉 # ...

  6. KEIL的ARM编译器对RW和ZI段的一个处理

    按照C编译器编译的结果,一般会产生RO段,RW段,ZI段.RO是程序中的指令和常量,RW是程序中的已初始化全局变量,ZI是程序中的未初始化或初始化为零的全局变量. 那么如下的代码 int aaa; i ...

  7. 转: Promises与Javascript异步编程

    在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这些年浏览器技术.HTML5以及CSS3等的发展,越来越多的富Web应用出现:在给与我们良好体验的同时,Web开发人员在背后需要处理越来越多 ...

  8. ElasticSearch D3

    http://www.elasticsearch.org/blog/data-visualization-elasticsearch-aggregations/

  9. Windows 系统消息范围和前缀,以及消息大全

    Windows系统定义的消息类别消息标识符前缀 消息分类ABM 应用桌面工具栏消息BM 按钮控件消息CB 组合框控件消息CBEM 扩展组合框控件消息CDM 通用对话框消息DBT 设备消息DL 拖曳列表 ...

  10. Mysql 忘密码 + Phpadmin 修改密码无法登陆

    mysql有时候忘记密码了怎么办?我给出案例和说明!一下就解决了! Windows下的实际操作如下 1.关闭正在运行的MySQL. 2.打开DOS窗口,转到mysql\bin目录. 3.输入mysql ...