一.synchronized
  java并发编程中存在“非线程安全"问题。“非线程安全"是指发生在多个线程对同一个对象中的实例变量并发访问时,产生的”脏读“现象,使用synchronized同步处理可解决这一问题。非线程安全问题存在于实例变量中,不存在方法内部的私有变量。
1、synchronized修饰方法的两种情况:
(1).当A线程调用某个对象的synchronized方法,先持有某个对象的锁;这时B线程需要等待A线程执行完毕后释放这个对象锁才可调用这个对象的synchronized方法,即同步。synchronized是一个独占锁,每个锁请求之间是互斥的
(2).当A线程调用某个对象的synchronized方法时,B线程调用这个对象的其他非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();
}
}

  可通过执行上面代码通过程序输出顺序证明以上结论的正确性。

 2、synchronized重入
可重入锁:即某个线程可以获得一个它自己已持有的锁。下面的例子在继承关系中子类可以通过可重入锁调用父类的同步方法,提升了加锁行为的封装性。如果没有可重入锁就会产生死锁。
父类:
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.死锁

    那什么是死锁呢? 下面是维基百科对死锁的定义:

  死锁(英语:Deadlock),又译为死结,计算机科学名词。当两个以上的运算单元,双方都在等待对方停止运行,以获取系统资源,但是没有一方提前退出时,就称为死锁。
       死锁的四个条件是
  禁止抢占 no preemption - 系统资源不能被强制从一个进程中退出
  持有和等待 hold and wait - 一个进程可以在等待时持有系统资源
  互斥 mutual exclusion - 只有一个进程能持有一个资源
  循环等待 circular waiting - 一系列进程互相持有其他进程所需要的资源
       死锁只有在这四个条件同时满足时出现。预防死锁就是至少破坏这四个条件其中一项,即破坏“禁止抢占”、破坏“持有等待”、破坏“资源互斥”和破坏“循环等待”。
 
下面这张图片清除的描述了死锁的发生:

编码证明:

/**
* @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.追踪、分析死锁发生

死锁检查方法,命令窗口运行:
1、jps
2、jstack -l 端口     //-l 选项用于打印锁的附加信息
 
 
下面是部分死锁信息:
 
死锁只有在这四个条件同时满足时出现。预防死锁就是至少破坏这四个条件其中一项,即破坏“禁止抢占”、破坏“持有等待”、破坏“资源互斥”和破坏“循环等待”。
 
5、最后是部分synchronized知识点补充:

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解析以及死锁分析排查的更多相关文章

  1. (二)对象以及变量的并发访问--synchronized的使用细节,用法

    具体的记录synchronized关键的各种使用方式,注意事项.感觉一步一步跟我来都可以看懂滴 大致是按照以下思路进行书写的.黑体字可以理解为结论, 1.synchronized锁的是什么? 2.sy ...

  2. Java多线程编程核心技术-第2章-对象及变量的并发访问-读书笔记

    第 2 章 对象及变量的并发访问 本章主要内容 synchronized 对象监视器为 Object 时的使用. synchronized 对象监视器为 Class 时的使用. 非线程安全是如何出现的 ...

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

    synchronized同步方法 "非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是"脏读",也就是渠道的数据其实是被更改 ...

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

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

  5. 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法

    主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...

  6. Java多线程编程核心 - 对象及变量的并发访问

    1.什么是“线程安全”与“非线程安全”? “非线程安全”会在多个线程对同一对象总的实例变量进行并发访问时发生,产生的后果是“脏读”,也就是取到的数据其实是被更改过的. “线程安全”是以获得的实例变量的 ...

  7. Java多线程——对象及变量的并发访问

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  8. Java——多线程之对象及变量的并发访问

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  9. 《JAVA多线程编程核心技术》 笔记:第二章:对象及变量的并发访问

    一.基本概念1.安全的变量和不安全的变量2.脏读的理解3.锁重入:4.锁释放5.死循环:二.synchronized 的理解:三.synchronized 同步方法3.1 同步方法不具有继承性.3.2 ...

随机推荐

  1. 思维题 HDOJ 5288 OO’s Sequence

    题目传送门 /* 定义两个数组,l[i]和r[i]表示第i个数左侧右侧接近它且值是a[i]因子的位置, 第i个数被选择后贡献的值是(r[i]-i)*(i-l[i]),每个数都枚举它的因子,更新l[i] ...

  2. TCP/IP与Http与socket的关系

    1 理清概念: TCP/IP是一个大的协议族(只不过TCP和IP是super star所以就这么命名了),它包括了: 应用层协议:FTP.HTTP.TELNET.SMTP.DNS(协议): 传输层协议 ...

  3. kafka_2.11-0.8.2.2.tgz的3节点集群的下载、安装和配置(图文详解)

    kafka_2.10-0.8.1.1.tgz的1或3节点集群的下载.安装和配置(图文详细教程)绝对干货 一.安装前准备 1.1 示例机器 二. JDK7 安装 1.1 下载地址 下载地址: http: ...

  4. Spring Boot (32) Lock 本地锁

    平时开发中,有时会双击提交表单造成重复提交,或者网速比较慢时还没有响应又点击了按钮,我们在开发中必须防止重复提交 一般在前台进行处理,定义个变量,发送请求前判断变量值为true,然后把变量设置为fal ...

  5. Linux shell命令之cat

    cat:查看文件的内容.连接文件.创建一个或多个文件和重定向输出到终端或文件  用法:cat [选项] [文件] 1. $ cat hello.txt 显示hello.txt文本文件中的内容 2. $ ...

  6. [ CCO 2015 ] Artskjid

    \(\\\) \(Description\) \(N\)个点\(M\)条边的有向图,求从\(0\)号节点出发,\(N-1\)号节点结束,且图中每个点至多经过一次的最长路. \(N\in[2,18]\) ...

  7. cocos2d-x android 环境部署

    1.下载jdk http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 2.下载 and ...

  8. firefox浏览器中 bootstrap 静态弹出框中select下拉框不能弹出(解决方案)

    问题出现场景1: 在firefox浏览器中在bootstrap弹出的modal静态框中再次弹出一个静态框时 select下拉框不能弹出选项 解决方案:去掉最外层静态框的 tabindex=" ...

  9. (转) 淘淘商城系列——redis-desktop-manager的使用

    http://blog.csdn.net/yerenyuan_pku/article/details/72849791 实际工作环境中,redis会安装在服务器上,我们想使用redis服务就要使用re ...

  10. PHP爬数据 QueryList

    QueryList官方文档:https://www.querylist.cc/docs/guide/v3 因为php版本使用5.6,所以使用QueryList v3版本,php7可以使用 v4版本 v ...