【JavaSE8 基础 Keyword】synchronized复杂实例解析 2019_7_26

第一类:对象锁实例

1.1同一实例的对象锁

对一个实例(对象)的异步方法、同步方法、同步陈述 访问实例

实例类代码

//异步、同步实例函数、同步对象(this)Statement陈述
public class SyncThread implements Runnable{
    @Override
    public void run() {
        //currentThread():Returns a reference to the currently executing thread object
        //getName():Returns this thread's name
        //对传入线程进行名称判断,分别执行不同的函数
        //(异步实例函数、同步实例函数,异步实例函数中的同步陈述)
        String threadName = Thread.currentThread().getName();
        if (threadName.startsWith("A")){
            try {
                async();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else if (threadName.startsWith("B")){
            try {
                syncStatemnet();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else if (threadName.startsWith("C")){
            try {
                syncInstance();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 异步实例函数:多个线程可同时访问类非同步(异步)函数async()
     * @throws InterruptedException
     */
    private void async() throws InterruptedException {
    	//打印,线程名+开始(格式化后的时间)    
        System.out.pr1intln(Thread.currentThread().getName()+"_Async_Start:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        Thread.sleep(2000);
        //打印,线程名+结束(格式化后的时间) 
        System.out.println(Thread.currentThread().getName()+"_Async_End:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }

    /**
     * 同步实例函数:每个线程执行此函数需要线获取对象锁,才能执行,否则阻塞(等待/挂起)
     * @throws InterruptedException
     */
    private synchronized void syncInstance() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"_SyncInstance_Start:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName()+"_SyncInstance_End:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }

    /**
     * 异步函数中的同步陈述:这个函数还是异步的,但里面有同步陈述
     * 所有线程都可先访问进入这个函数,但执行到同步陈述时,需要先获取对象锁,否则阻塞
     * @throws InterruptedException
     */
    private void syncStatemnet() throws InterruptedException {
        //异步实例函数中的非同步Statement
        System.out.println(Thread.currentThread().getName() + "_SyncStatemnet()_HasIn:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
		//异步实例函数中的同步Statement
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + "_SyncStatemnet_Start:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + "_SyncStatemnet_End:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }
}

测试类主函数代码

public class SyncTest {
    public static void main(String[] args) {
        SyncThread syncThread = new SyncThread();
        //A 普通实例函数,异步【可被多个线程同时访问】
        Thread A_thread1 = new Thread(syncThread, "A_thread1");
        Thread A_thread2 = new Thread(syncThread, "A_thread2");

        //B 修饰陈述Statement,同步【同步Statement会被线程独占】
        Thread B_thread1 = new Thread(syncThread, "B_thread1");
        Thread B_thread2 = new Thread(syncThread, "B_thread2");

        //C 修饰实例函数,同步【同步实例函数会被线程独占】
        Thread C_thread1 = new Thread(syncThread, "C_thread1");
        Thread C_thread2 = new Thread(syncThread, "C_thread2");
        A_thread1.start();
        A_thread2.start();
        B_thread1.start();
        B_thread2.start();
        C_thread1.start();
        C_thread2.start();
    }

结果解析

双击可放大
sync解析图
结果分析1:

同一个对象的两个线程,访问异步函数,是同时执行的

同一个对象的两个线程,访问同步实例函数,是不能同时进行的,需要等待上一个线程完成,下一个线程才能执行

同一个对象的两个线程,访问同步陈述,是不能同时进行的,但非同步陈述的语句仍是异步语句,是同时执行的

1.2不同实例的对象锁

对不同实例(对象),访问各自的异步方法、同步方法陈述实例

实例类代码

同1.1实例类代码

测试类主函数代码

修改1.1测试类代码

public class SyncTest {
    public static void main(String... args) {
    	//删除 SyncThread syncThread = new SyncThread();
    	//为每一个线程都new一个不同的SyncThread对象。
        Thread A_thread1 = new Thread(new SyncThread(), "A_thread1");
        Thread A_thread2 = new Thread(new SyncThread(), "A_thread2");
        Thread B_thread1 = new Thread(new SyncThread(), "B_thread1");
        Thread B_thread2 = new Thread(new SyncThread(), "B_thread2");
        Thread C_thread1 = new Thread(new SyncThread(), "C_thread1");
        Thread C_thread2 = new Thread(new SyncThread(), "C_thread2");
        A_thread1.start();
        A_thread2.start();
        B_thread1.start();
        B_thread2.start();
        C_thread1.start();
        C_thread2.start();
    }
}

结果解析

//console
A_thread1_Async_Start:23:55:37
C_thread2_SyncInstance_Start:23:55:37
B_thread2_SyncStatemnet()_HasIn:23:55:37
A_thread2_Async_Start:23:55:37
C_thread1_SyncInstance_Start:23:55:37
B_thread1_SyncStatemnet()_HasIn:23:55:37
B_thread2_SyncStatemnet_Start:23:55:37
B_thread1_SyncStatemnet_Start:23:55:37
    
A_thread1_Async_End:23:55:39
C_thread2_SyncInstance_End:23:55:39
A_thread2_Async_End:23:55:39
C_thread1_SyncInstance_End:23:55:39
B_thread2_SyncStatemnet_End:23:55:39
B_thread1_SyncStatemnet_End:23:55:39

结果分析2:
两个线程访问不同对象的 synchronized(this|object) {} 代码块和 synchronized 修饰非静态方法是异步的,因为对象锁是针对一个对象而言的,多个对象的对象锁是相互独立存在。

同一个类的不同对象(实例)的对象锁互不干扰,相互独立。
在这里插入图片描述

第二类:类锁实例

2.1同一实例的类锁

实例类代码

修改SyncThread类的同步实例方法为同步静态(类)方法
及修改同步Statement this为SyncThread.class
以下仅给出修改部分的代码

	//同步实例方法改为同步静态(类)方法
	//加static修饰符
	private synchronized static void syncInstance() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"_SyncInstance_Start:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName()+"_SyncInstance_End:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }
	//this改为SyncThread.class
	private void syncStatemnet() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "_SyncStatemnet()_HasIn:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        //原this改为SyncThread.class
        synchronized (SyncThread.class) {
            System.out.println(Thread.currentThread().getName() + "_SyncStatemnet_Start:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + "_SyncStatemnet_End:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }

测试类主函数代码

1.1同一实例的对象锁测试类主函数代码

结果解析

//console
B_thread2_SyncStatemnet()_HasIn:00:38:59
C_thread2_SyncInstance_Start:00:38:59
B_thread1_SyncStatemnet()_HasIn:00:38:59
A_thread2_Async_Start:00:38:59
A_thread1_Async_Start:00:38:59

A_thread2_Async_End:00:39:01
C_thread2_SyncInstance_End:00:39:01
B_thread1_SyncStatemnet_Start:00:39:01
A_thread1_Async_End:00:39:01

B_thread1_SyncStatemnet_End:00:39:03
B_thread2_SyncStatemnet_Start:00:39:03

B_thread2_SyncStatemnet_End:00:39:05
C_thread1_SyncInstance_Start:00:39:05

C_thread1_SyncInstance_End:00:39:07

结果分析:
异步方法(B_thread1&2_SyncStatemnet()_HasIn,A_thread1&2_Async_Start)同时开始
虽然A1,A2,B1,B2是同时开始(当然B1,B2开始的是异步语句,还有同步陈述没有运行)但A1,A2在2s后同时结束,而全部的类方法及类陈述需要一个一个排队执行。
同步静态(类)方法C2(Start:00:38:59)先开始,2s后C2(End:00:39:01)结束
然后静态陈述B1(Start:00:39:01)再开始,2s后B1(End:00:39:03)结束
然后静态陈述B2(Start:00:39:03)再开始,2s后B2(End:00:39:05)结束
然后静态(类)方法C1(Start:00:39:05)再开始,2s后C1(End:00:39:07)结束
一个停车场出口,4辆车排队交费出去。共耗费了38:59-39:07,8s时间

也就是,同一实例的类方法与获取.class的类陈述都是排一个队来执行自己的代码。
与对象锁的,同一实例的实例方法与获取this的实例陈述是一样的。

2.2不同实例的类锁

实例类代码

同上2.1同一实例的类锁的实例类代码

测试类主函数代码

同1.2不同实例的对象锁的测试类主函数代码

结果解析

测试结果:

//console
A_thread1_Async_Start:00:42:31
B_thread2_SyncStatemnet()_HasIn:00:42:31
C_thread1_SyncInstance_Start:00:42:31
B_thread1_SyncStatemnet()_HasIn:00:42:31
A_thread2_Async_Start:00:42:31
A_thread1_Async_End:00:42:33
C_thread1_SyncInstance_End:00:42:33
B_thread1_SyncStatemnet_Start:00:42:33
A_thread2_Async_End:00:42:33
B_thread1_SyncStatemnet_End:00:42:35
B_thread2_SyncStatemnet_Start:00:42:35
B_thread2_SyncStatemnet_End:00:42:37
C_thread2_SyncInstance_Start:00:42:37
C_thread2_SyncInstance_End:00:42:39

结果分析:
两个线程访问不同对象的 synchronized(类.class)陈述 {} 或 synchronized 修饰静态方法还是同步的。对于同一个类的不同对象的类锁是同一个,类锁是类不同对象共享的。
在这里插入图片描述

第三类:类锁对象锁均有

一个类同时有对象锁(this/实例方法)类锁(.class/静态方法)

同一类同一对象

同一对象会有怎样影响?

结论

一个类,可以同时拥有 synchronized 修饰的实例方法(对象锁)、静态方法(类锁)。
这两个同步方法(类/对象锁)通过 同一个对象的不同线程 是 可以同时执行/访问的。

同一类不同对象

两个对象会有怎样影响?

结论

同一类的两个对象的对象锁方法同时执行,同一类的两个对象的类锁方法排队执行。

总结

对象锁 与 类锁相互独立,工作性质相同,只是管辖范围不同。
对象锁一个是管实例函数及实例陈述,类锁管类函数及类陈述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值