在多线程访问同一个对象中的不同的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. 【转】linux Centos 6.5 安装桌面环境GNOME

    在某种场合之下,我们使用的Linux还是要选择安装桌面环境的,所以在这里介绍一下如何给没有安装桌面环境的系统安装桌面环境. 以Centos 6.5 为例演示一下如何安装桌面环境. 一.首先查看系统的运 ...

  2. .net mvc笔记3_Understanding Razor Syntax

    Understanding Razor Syntax MVC3新视图引擎的名字叫做Razor.ASP.NET视图引擎处理web页面,寻找包含在服务器端指令的特殊元素.正如我们前面已经提到的,标准的AS ...

  3. 修改IIS虚拟目录名称

    @echo off echo ------------------------------------------------------------------------------ echo - ...

  4. 解决:eclipse导入android时工程下没有R文件的问题,以及style.xml文件报错

    解决:eclipse导入android时工程下没有R文件的问题,以及style.xml文件报错

  5. 在 Windows Azure 上部署预配置 Oracle VM

    Microsoft 和 Oracle 近期宣布建立战略合作伙伴关系,基于此,我们将通过 Windows Azure 镜像库推出多种常用的 Oracle 软件配置.即日起,客户可以在 Windows S ...

  6. zoj 3490

    蛋都疼了,高了半天,Output Limit Exceeded 原来是输入的问题,我靠!!以后还是用输入输出c++好,这尼玛!!郁闷!!!!! #include<stdio.h> #inc ...

  7. zoj 3710 Friends

    #include<stdio.h> #include<string.h> ][],h; int main(int argc, char* argv[]) { int t,i,n ...

  8. WPF之DataGrid应用(转)

    原文:http://blog.csdn.net/sanjiawan/article/details/6785394 前几天打算尝试下DataGrid的用法,起初以为应该很简单,可后来被各种使用方法和功 ...

  9. quartz 定时调度持久化数据库配置文件

    1 下载quartz对应版本jar包 2 初始化对应数据库sql(版本需要对应,不然会出现少字段的情况) ,下载地址  https://github.com/quartz-scheduler/quar ...

  10. Sublime 编辑器主题

    Sublime主题分为两种 一种是编辑框中的代码的颜色  另一种是编辑器本身的颜色(不只是颜色哟  Sublime编辑器左边侧边栏的字很小对不对 !有了主题就可以改) 这个主题叫做Soda  http ...