在多线程访问同一个对象中的不同的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. 【LeetCode题意分析&解答】36. Valid Sudoku

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  2. No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=armv7 armv7s)

    In Build Settings are: Architectures: Starndard (armv7, armv7s) Base SDK: Latest iOS (iOS 6.0) Build ...

  3. Gulp browserify livereload

    Gulp browserify livereload 之前在browserify那个博文中介绍了gulp + browserify 不过那个配置还不能满足日常需要 搬运 https://github. ...

  4. Jsoup代码解读之一-概述

    Jsoup代码解读之一-概述 今天看到一个用python写的抽取正文的东东,美滋滋的用Java实现了一番,放到了webmagic里,然后发现Jsoup里已经有了…觉得自己各种不靠谱啊!算了,静下心来学 ...

  5. Git库文件的状态

    git库所在的文件夹(即.git所在的文件夹)中的文件的状态: (1)untracked:未跟踪,此文件在文件夹中,但并没有加入git库,不参与版本控制. 通过”git add”,”git commi ...

  6. Android 支付宝钱包手势password裂纹战斗

    底 随着移动互联网和手机屏幕越做越大的普及等..购物在移动设备上.消费是必不可少的人们习惯于生活. 随着这股浪潮的兴起,安全.便捷的移动支付的需求也越来越大.故,各大互联网公司纷纷推出了移动支付平台. ...

  7. VS2015自定义注释内容

    一直想自动添加一些注释信息,找了好多种方式:各种插件什么的,最后偶然发现可以修改vs的模板可以做到,下面介绍如何改 首先找到vs的安装目录,如下是我的安装目录: D:\Program Files\VS ...

  8. Jquery的一些取值

    //获取当前节点的html代码(包括当前节点),prop用于获取与设置Html元素的原生属性 $("#tmpMsgObj").prop("outerHTML") ...

  9. ajax post传值

    一.字符串             $.ajax({                type: "POST",                data: {"ID&quo ...

  10. Android应用开发基础篇(7)-----BroadcastReceiver

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/22/2363644.html 一.概述 BroadcastReceiver,意思就是广播信息接收 ...