多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。
这说明synchronized同步方法或synchronized(this)同步代码块分别有两种作用
(1)synchronized同步方法
1)对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态
2)同一时间只有一个线程可以执行synchronized同步方法中的代码
(2)synchronized(this)同步代码块
1)对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态
2)同一时间只有一个线程可以执行synchronized(this)同步代码块中的代码
Java还支持对“任意对象”作为“对象监视器”来实现同步的功能。这个“任意对象”大多数是实例变量及方法的参数,使用synchronized(非this对象)
synchronized(非this对象)格式的作用只有1中:synchronized(非this对象x)同步代码块
1)在多个线程持有“对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码
2)当持有“对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码。
package synBlockString;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class Service {
private String usernameParam;
private String passwordParam;
private String anyString = new String();
public void setUsernamePassword(String username,String password){
try{
synchronized (anyString){
System.out.println("线程名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入同步");
usernameParam = username;
Thread.sleep(2000);
passwordParam = password;
System.out.println("线程名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开同步");
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
package synBlockString;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service){
super();
this.service = service;
} public void run(){
service.setUsernamePassword("a","aa");
}
}
package synBlockString;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service){
super();
this.service = service;
}
public void run(){
service.setUsernamePassword("b","bb");
} }
package synBlockString;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String [] args){
Service service = new Service();
ThreadA threadA = new ThreadA(service);
threadA.setName("A");
threadA.start();
ThreadB threadB = new ThreadB(service);
threadB.setName("B");
threadB.start();
threadB.start(); }
}
线程名称为:A在1484823811547进入同步
线程名称为:A在1484823813559离开同步
线程名称为:B在1484823813559进入同步
线程名称为:B在1484823815573离开同步

如果修改service.java为

package synBlockString;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class Service {
private String usernameParam;
private String passwordParam; public void setUsernamePassword(String username,String password){
try{
String anyString = new String();
synchronized (anyString){
System.out.println("线程名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入同步");
usernameParam = username;
Thread.sleep(2000);
passwordParam = password;
System.out.println("线程名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开同步");
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
线程名称为:A在1484823870625进入同步
线程名称为:B在1484823870625进入同步
线程名称为:B在1484823872638离开同步
线程名称为:A在1484823872638离开同步

所以,使用synchronized(非this对象)同步代码块格式进行同步操作时,对象监视器必须是同一个对象,如果不是同一个对象监视器,运行的结果就是异步调用了,就会交叉运行。

再看下一个示例:

package synBlockString2;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class Service {
private String anyThing = new String();
public void a(){
try {
synchronized (anyThing){
System.out.println("a begin");
Thread.sleep(2000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void b(){
System.out.println(" b begin");
System.out.println(" b end");
}
}
package synBlockString2;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service){
super();
this.service = service;
}
public void run(){
service.a();
}
}
package synBlockString2;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service){
super();
this.service = service ;
}
public void run(){
service.b();
}
}
package synBlockString2;

/**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String [] args){
Service service = new Service();
ThreadA threadA = new ThreadA(service);
threadA.setName("A");
threadA.start();
ThreadB threadB = new ThreadB(service);
threadB.setName("B");
threadB.start();
}
}
运行结果:
a begin
b begin
b end
a end

由于对象监视器不同,所以运行结果就是异步的

同步代码块放在非同步synchronized方法中进行声明,并不能保证调用方法的线程的执行同步/顺序性,也就是线程调用方法的顺序是无序的,虽然在同步块中执行的顺序是同步的,这样就容易出现脏读问题。

synchronized将任意对象作为对象监视器的更多相关文章

  1. Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁 ...

  2. java中synchronized 用在实例方法和对象方法上面的区别

    https://bijian1013.iteye.com/blog/1836575 在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法.也可以s ...

  3. Java反射机制demo(二)—通过Class实例化任意类的对象

    Java反射机制demo(二)—通过Class实例化任意类的对象 上一章节中,实例化了Class类对象的实例,这个部分的demo展示了如何使用Class对象的实例去获得其他类的对象的实例. 任意一个类 ...

  4. 将任意一个jQuery对象进行表单序列化,免除了提交请求时大量拼写表单数据的烦恼,支持键值对<name&value>格式和JSON格式。

    http://zhengxinlong.iteye.com/blog/848712 将任意一个jQuery对象进行表单序列化,免除了提交请求时大量拼写表单数据的烦恼,支持键值对<name& ...

  5. JS对象 Date 日期对象 日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒)。 定义一个时间对象 : var Udate=new Date();Date()的首字母须大写

    Date 日期对象 日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 定义一个时间对象 : var Udate=new Date(); 注意:使用关键字new,Date()的首 ...

  6. 锁对象-条件对象-synchronized关键字

    1 import java.util.concurrent.locks.Condition; 2 import java.util.concurrent.locks.Lock; 3 import ja ...

  7. JavaScript中Date(日期对象),Math对象--学习笔记

    Date对象 1.什么是Date对象? 日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 语法:var Udate=new Date();  注:初始值为当前时间(当前电脑系统 ...

  8. JS 字符串对象 数组对象 函数对象 函数作用域

    一.内置对象 object对象:ECMAScript 中的所有对象都由这个对象继承而来:Object 对象中的所有属性和方法都会出现在其他对象中 ToString() : 返回对象的原始字符串表示.V ...

  9. 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文

    在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...

随机推荐

  1. pip下载保存Python包,pip离线安装

    新版pip下载安装包命令: pip download  -r requirements.txt  -d  /tmp/paks/ 在linux下       1.下载指定的包到指定文件夹.       ...

  2. NFS服务的端口分配

    常规的一些NFS服务设置我们已经了解了.那么对于端口问题,很多朋友并不是很清楚.这里我们就来详细介绍一下端口的分配.portmapper在NFS服务启动的时候给每一个NFS服务分配了一个动态的端口,如 ...

  3. ssh加密公私钥

    SSH公钥登录原理 在平时工作中我们经常要远程登录服务器,这就要用到SSH协议: $ ssh user@host 主要有两种登录方式:第一种为密码口令登录,第二种为公钥登录 密码口令登录 通过密码进行 ...

  4. centos7+ docker1.12 实践部署docker及配置direct_lvm

    前言 Docker现在在后端是那么的火热..尤其当笔者了解了docker是什么.能做什么之后,真的是感觉特别的exciting,便迫不及待的去实践部署一下. 但是在实际部署中,因为笔者使用的是阿里云e ...

  5. 周末大礼:jQuery技巧总结

    一.简介 1.1.概述 随着WEB2.0及ajax思想在互联网上的快速发展传播,陆续出现了一些优秀的Js框架,其中比较著名的有Prototype.YUI.jQuery.mootools.Bindows ...

  6. array、isset、三元运算符、find()

    array('name','getName',3,'callback'), // 对name字段在新增和编辑的时候回调getName方法 if(isset($_GET['id'])) { // 根据i ...

  7. TensorFlow基础笔记(14) 网络模型的保存与恢复_mnist数据实例

    http://blog.csdn.net/huachao1001/article/details/78502910 http://blog.csdn.net/u014432647/article/de ...

  8. C++ 类的复制控制

    写了又删,删了又写,才发现这一章节不好描述. 那就假定个前提吧,假定已经知道: ① C++的类有构造函数. ② 如果不提供任何构造函数,那编译器会生成默认的无参构造函数--默认构造函数只会进行成员变量 ...

  9. Linux中vi的使用

    首先,如果vi中出现了方向键变成ABCD的情况,需要卸载默认的vim-common,再安装vim. sudo apt-get remove vim-common sudo apt-get instal ...

  10. Pacbio 纯三代组装复活草基因组

    对于植物等真核生物基因组来说,重复序列, 多倍体,高杂合度等特征在利用二代数据进行组装的时候都会有很大的问题: 利用二代数据组装出来的基因组,大多达不到完成图的水准,通常只是覆盖到编码蛋白的基因区域, ...