对象和变量的并发访问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 ...
随机推荐
- Html5 编程题
1.请写出下面所示的控件的html 代码? <div> <div><a>姓名:</a><input type="text" ...
- 【洛谷2617_BZOJ1901】Dynamic Rankings(树套树)
题目: 洛谷 2617 BZOJ 1901 是权限题,\(n=10^4\) ,内存 128 MB :洛谷 2617 \(n=10^5\) ,内存 1024 MB ,数据比较坑. 分析: 蒟蒻初学树套树 ...
- pyinstaller打包报错:AttributeError: 'str' object has no attribute 'items'
导致原因和python多数奇奇怪怪的问题一样,依赖包的版本问题. 解决办法: 对setuptools这个包进行升级,链接在这里 https://pypi.org/project/setuptools/ ...
- connection failed to http://nssa-sensor3:11000/oozie/?user.name=oozie(<urlopen erroer Errno 111] Connection refused>)解决办法(图文详解)
不多说,直接上干货! 解决办法 Copy/Paste oozie.services property tag set from oozie-default.xml to oozie-site.xml. ...
- 图片分离,试用于各种文件跨站传输,post方法传输
主要思想:把不通形式的文件或者文字,以字节编码流的形式传递过去然后反解析后重新生成原文件 //------------------------------发送部分------------------- ...
- EasyUI系列学习(十一)-Accordion(分类)
一.加载 1.class加载 <div class="easyui-accordion" style="width:300px;height:200px" ...
- Java常见面试问题: equals()与hashCode()的使用
目录 1 equals()与'=='的区别 2 equals()方法的重写规则 3 为什么重写equals()的同时还需要重写hashCode() 4 JDK 7中对hashCode()方法的改进 5 ...
- Angular JS中自定义标签 属性绑定的解释
看到自定义标签的文档时,文档作者解释的能力实在太弱,也可能是本人太笨,一下绕不过来. 看了一个stackoverflow答案,才算明白,在此贴出翻译,以供大家参考. .csharpcode, .csh ...
- Python学习日记之文件读取操作
Python内置了文件读写的函数open,read 用法示例: open('/home/root/files.txt ') 在打开文件后,操作完成后可以使用close()关闭文件,但比较好的文件读写方 ...
- C# 客户端读取共享目录文件
控制台应用程序 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...