下面验证上面三条结论

验证第一条结论:

package Second;

public class MyObject {
}
package Second;

public class Service {

    public void testMethod1(MyObject object) {
synchronized (object) {
try {
System.out.println("testMethod1 ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("testMethod1 releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
package Second;

public class ThreadA extends Thread {

    private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class ThreadB extends Thread {
private Service service;
private MyObject object; public ThreadB(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class Run1_1 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object);
b.setName("b");
b.start();
} }

同步的原因是使用了同一个“对象监视器“”。如果使用不同的“”对象监视器“”会出现什么效果呢?见下面

package Second;

public class Run1_2 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }
package Second;

public class Run1_2 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }

验证第2个结论

package Second;

public class MyObject {
synchronized public void speedPrintString() {
System.out.println("speedPrintString ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
System.out.println("-----------------");
System.out.println("speedPrintString releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
}
}
package Second;

public class Service {

    public void testMethod1(MyObject object) {
synchronized (object) {
try {
System.out.println("testMethod1 ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("testMethod1 releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
package Second;

public class ThreadA extends Thread {

    private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class ThreadB extends Thread {
private MyObject object; public ThreadB(MyObject object) {
super();
this.object = object;
} @Override
public void run() {
super.run();
object.speedPrintString();
}
}
package Second;

public class Run {

    public static void main(String[] args) throws InterruptedException {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); Thread.sleep(100); ThreadB b = new ThreadB(object);
b.setName("b");
b.start();
} }

验证第3个结论

其他代码与第二个实验相同

package Second;

public class MyObject {
public void speedPrintString() {
synchronized (this) {
System.out.println("speedPrintString ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
System.out.println("-----------------");
System.out.println("speedPrintString releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+ Thread.currentThread().getName());
}
}
}

静态同步synchronized方法与synchronized(class)代码块

是对当前的*.java文件对应的class类进行持锁

package Second;

public class Service {

    synchronized public static void printA() {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public static void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second;

public class ThreadA extends Thread {
@Override
public void run() {
Service.printA();
} }
package Second;

public class ThreadB extends Thread {
@Override
public void run() {
Service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        ThreadA a = new ThreadA();
a.setName("A");
a.start(); ThreadB b = new ThreadB();
b.setName("B");
b.start(); } }

下面展示synchronized关键字加到非static静态方法上的锁

package Second;

public class Service {

    synchronized public static void printA() {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public static void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} synchronized public void printC() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printC");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printC");
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
} }
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class ThreadC extends Thread {

    private Service service;

    public ThreadC(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printC();
}
}

异步的原因是持有不同的锁,一个是对象锁,另外一个是class锁,而class锁可以对类的所有对象实例起作用,下面验证

package Second;

public class Service {

    synchronized public static void printA() {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public static void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }

同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。下面测试

package Second;

public class Service {

    public static void printA() {
synchronized (Service.class) {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
} } public static void printB() {
synchronized (Service.class) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }

数据类型String的常量池特性

package Second;

public class Service {
public static void print(String stringParam) {
try {
synchronized (stringParam) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second;

public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service = new Service();

        ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

出现这样的情况就是因为String的两个值都是AA,两个线程持有相同的锁,所以造成线程B不能执行。这就是String常量池所带来的问题。

因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他的,比如new object()实例化一个object对象,但它并不放入缓存中。

package Second;

public class Service {
public static void print(Object object) {
try {
synchronized (object) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service = new Service();

        ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

交替打印是因为持有的锁不是同一个

同步synchronized方法无限等待与解决

同步方法容易造成死循环

package Second;

public class Service {
synchronized public void methodA() {
Object object1 = new Object(); System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end"); } synchronized public void methodB() {
Object object2 = new Object(); System.out.println("methodB begin");
System.out.println("methodB end"); }
}
package Second;

public class ThreadA extends Thread {

    private Service service;

    public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodA();
} }
package Second;

public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodB();
} }
package Second;

public class Run {

    public static void main(String[] args) {
Service service = new Service(); ThreadA athread = new ThreadA(service);
athread.start(); ThreadB bthread = new ThreadB(service);
bthread.start();
} }

线程B永远得不到运行的机会,锁死了

package Second;

public class Service {
public void methodA() {
Object object1 = new Object();
synchronized (object1) {
System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end");
}
} public void methodB() {
Object object2 = new Object();
synchronized (object2) {
System.out.println("methodB begin");
System.out.println("methodB end");
}
}
}

《Java多线程编程核心技术》读后感(五)的更多相关文章

  1. java多线程编程核心技术——第五章总结

    定时器Timer的使用 1.1方法schedule(TimerTask task, Date time)的测试 1.2方法schedule(TimerTask task, Date firstTime ...

  2. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  3. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  4. Java多线程编程核心技术(一)Java多线程技能

    1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...

  5. 《Java多线程编程核心技术》知识梳理

    <Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...

  6. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  7. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  8. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  9. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  10. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

随机推荐

  1. java 多参实现

    package com.northeasttycoon.monitor.service; import static java.lang.System.out; /** * Created by no ...

  2. sql server单引号和双引号的区别

    --当 SET QUOTED_IDENTIFIER 为 ON 时,标识符可以由双引号分隔,而文字必须由单引号分隔--当 SET QUOTED_IDENTIFIER 为 OFF(默认值)时,表达式中的文 ...

  3. 九度OJ 1076:N的阶乘 (数字特性、大数运算)

    时间限制:3 秒 内存限制:128 兆 特殊判题:否 提交:6384 解决:2238 题目描述: 输入一个正整数N,输出N的阶乘. 输入: 正整数N(0<=N<=1000) 输出: 输入可 ...

  4. 【模板】区间第k小

    [模板]区间第k小 我实在是太弱了现在才会这个东西QAQ. 主席树做法. 一张关于主席树的无字说明 线段树\(2\)是只单点修改了实心酒红色点的线段树\(2\),线段树\(2\)中的蓝色节点实际上就是 ...

  5. 流畅的python学习笔记:第十三章:重载运算符__add__,__iadd__,__radd__,__mul__,__rmul__,__neg__,__eq__,__invert__,__pos__

    在前面第十章以及第一章的时候介绍了Vector对象的运算符重载.第十三章专门介绍运算符重载.这里我们看几个之前没讲过的运算符__neg__,__pos__,__invert__ class Vecto ...

  6. swift开发学习笔记-闭包

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jiangqq781931404/article/details/32913421 文章转自:http ...

  7. [证书服务器 第二篇] 基于OpenSSL 在 CentOS6 系统上 搭建自签证书服务,并应用于Web容器

    第一部分:概述 .. 第二部分:环境准备 1 操作系统 CentOS 6.x 2 安装openssl yum install -y openssl 3 安装jdk 从官网下载JDK http://ww ...

  8. Mac下php版本不支持imagetfftext函数问题

    brew rm freetype jpeg libpng gd zlib brew install freetype jpeg libpng gd zlib brew install php71 ht ...

  9. PAT 甲级 1104. Sum of Number Segments (20) 【数学】

    题目链接 https://www.patest.cn/contests/pat-a-practise/1104 思路 最容易想到的一个思路就是 遍历一下所有组合 加一遍 但 时间复杂度 太大 会超时 ...

  10. consider increasing the maximum size of the cache.

    虚拟机上搭建jenkins,出现unable to free [10] percent of the cache for Context [/jenkins] 提示让我加大缓存 consider in ...