对象和变量的并发访问synchronized解析以及死锁分析排查
/**
* @author monkjavaer
* @date 2018/11/26 21:12
*/
public class Service2 {
/**
* 同步方法
*/
public synchronized void printService() {
System.out.println(Thread.currentThread().getName() + " " + "start printService thread");
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + "printService end ");
} /**
* 同步方法
*/
public synchronized void printServiceOther() {
System.out.println(Thread.currentThread().getName() + " " + "start printServiceOther thread");
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + "printServiceOther end ");
} /**
* 非同步方法
*/
public void printServiceNotSynchronized() {
System.out.println(Thread.currentThread().getName() + " " + "start printServiceNotSynchronized thread");
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + "printServiceNotSynchronized end ");
}
}
线程A:
public class Syn2ThreadA extends Thread{
private Service2 service;
public Syn2ThreadA(Service2 service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.printService();
}
}
线程B:
public class Syn2ThreadB extends Thread{
private Service2 service;
public Syn2ThreadB(Service2 service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.printServiceNotSynchronized();
}
}
线程C:
public class Syn2ThreadC extends Thread{
private Service2 service;
public Syn2ThreadC(Service2 service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.printServiceOther();
}
}
测试方法:
public class Syn2Test {
public static void main(String[] args) {
Service2 service = new Service2();
//Syn2ThreadA调用了同步方法
Syn2ThreadA threadA = new Syn2ThreadA(service);
threadA.setName("threadA");
//Syn2ThreadB调用非同步
Syn2ThreadB threadB = new Syn2ThreadB(service);
threadB.setName("threadB");
//Syn2ThreadC调用了同步方法
Syn2ThreadC threadC = new Syn2ThreadC(service);
threadC.setName("threadC");
threadA.start();
threadB.start();
threadC.start();
}
}
可通过执行上面代码通过程序输出顺序证明以上结论的正确性。
public class Fruit {
public synchronized void dosomething(){
System.out.println("printFruit");
}
}
子类:
public class Apple extends Fruit {
@Override
public synchronized void dosomething() {
super.dosomething();
System.out.println("apple");
}
}
3.死锁
那什么是死锁呢? 下面是维基百科对死锁的定义:

编码证明:
/**
* @author monkjavaer
* @date 2018/11/26 22:37
*/
public class TestDeadlock { static final String resource1 = "resource1";
static final String resource2 = "resource2"; static class ThreadA extends Thread {
@Override
public void run() {
synchronized (resource1) {
System.out.println("ThreadA: locked resource 1");
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource2) {
System.out.println("ThreadA: locked resource 2");
}
}
}
} static class ThreadB extends Thread {
@Override
public void run() {
synchronized (resource2) {
System.out.println("ThreadB: locked resource 2");
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource1) {
System.out.println("ThreadB: locked resource 1");
}
}
}
} public static void main(String[] args) {
ThreadA threadA = new ThreadA();
threadA.setName("====ThreadA====");
ThreadB threadB = new ThreadB();
threadB.setName("====ThreadB====");
threadA.start();
threadB.start();
}
}
上面的代码运行时会产生死锁情况。
4.追踪、分析死锁发生


a、synchronized同步方法弊端:如果一个线程调用同步方法要执行很长时间,那么其他线程要调用这个同步方法必须等待很长时间。
可以用synchronized解决,不在synchronized块中的代码异步执行。并且synchronized块synchronized方法是一样的使用的对象监视器是一个,他们都是锁定的当前对象。
b、synchronized同步不能被继承。
c、synchronized加到静态方法上时是给class类上锁,加到非静态方法是给对象上锁。
d、一般synchronized块不用String作为锁对象,因为String常量池有缓存功能。导致锁对象可能一直是相同的。
String a = "a";
String b = "a";
System.out.println(a==b);
比如上面的代码得到的结果是true
对象和变量的并发访问synchronized解析以及死锁分析排查的更多相关文章
- (二)对象以及变量的并发访问--synchronized的使用细节,用法
具体的记录synchronized关键的各种使用方式,注意事项.感觉一步一步跟我来都可以看懂滴 大致是按照以下思路进行书写的.黑体字可以理解为结论, 1.synchronized锁的是什么? 2.sy ...
- Java多线程编程核心技术-第2章-对象及变量的并发访问-读书笔记
第 2 章 对象及变量的并发访问 本章主要内容 synchronized 对象监视器为 Object 时的使用. synchronized 对象监视器为 Class 时的使用. 非线程安全是如何出现的 ...
- Java多线程编程核心技术---对象及变量的并发访问(一)
synchronized同步方法 "非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是"脏读",也就是渠道的数据其实是被更改 ...
- Java多线程编程核心技术(二)对象及变量的并发访问
本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...
- 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法
主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...
- Java多线程编程核心 - 对象及变量的并发访问
1.什么是“线程安全”与“非线程安全”? “非线程安全”会在多个线程对同一对象总的实例变量进行并发访问时发生,产生的后果是“脏读”,也就是取到的数据其实是被更改过的. “线程安全”是以获得的实例变量的 ...
- Java多线程——对象及变量的并发访问
Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...
- Java——多线程之对象及变量的并发访问
Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...
- 《JAVA多线程编程核心技术》 笔记:第二章:对象及变量的并发访问
一.基本概念1.安全的变量和不安全的变量2.脏读的理解3.锁重入:4.锁释放5.死循环:二.synchronized 的理解:三.synchronized 同步方法3.1 同步方法不具有继承性.3.2 ...
随机推荐
- 生成自签名ca 证书 使nginx 支持https
创建服务器私钥,命令会让你输入一个口令:$ openssl genrsa -des3 -out server.key 1024创建签名请求的证书(CSR):$ openssl req -new -ke ...
- 使用JS分页 <span> beta 1.0
<html> <head> <title>分页</title> <style> #titleDiv{ width:500px; backgr ...
- 图灵机(转自wiki)
图灵机(英语:Turing machine),又称确定型图灵机,是英国数学家艾伦·图灵于1936年提出的一种抽象计算模型,其更抽象的意义为一种数学逻辑机,可以看作等价于任何有限逻辑数学过程的终极强大逻 ...
- 237 Delete Node in a Linked List 删除链表的结点
编写一个函数,在给定单链表一个结点(非尾结点)的情况下,删除该结点. 假设该链表为1 -> 2 -> 3 -> 4 并且给定你链表中第三个值为3的节点,在调用你的函数后,该链表应变为 ...
- Silverlight环境配置
今天对Silverlight安装环境进行了配置,本系统已经安装VS2010 和 Silverlight 5. 要开发Silverlight必须安装Developer Runtime 和 SDK , 且 ...
- 25 C#类的继承
继承是面向对象编程的一个重要特性.任何类都可以从另一个类中继承,这就是说,这个类拥有它继承的类的所有成员.在OOP 中,被继承的类称为父类(也称为基类).注意,C#中的对象仅能直接派生于一个基类,当然 ...
- javascript异步下载 Promise实现
一般下载都是直接打开一个链接就行.var URL = 'XXXX';window.open(URL)其实这样会有些问题:1. 浏览器禁止打开新窗口,导致无法下载 那么怎么解决呢?这样: <a h ...
- 如何取消android studio启动时自动打开上次关闭的项目
Androidstudio默认每次android studio启动就会自动打开上次关闭的项目,如果想要取消并让它显示此界面 只需要
- TensorFlow OOM when allocating tensor with shape[5000,384707]
在session范围内不要进行eval()或者convert_to_tensor()操作, 否则会造成OOM,或者报出错误:GraphDef cannot be larger than 2GB usi ...
- redhat之数据挖掘R语言软件及rstudio-server服务的安装
安装时间:2015年8月25日 22:55:35 作者:luomg 软件:R.Rstudio-server 环境:redhat6.2 联系:luomgf@163.com 声明:如果你有遇到安装中的问题 ...