一.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. 转载使用 ContentObsever 拦截短信,获取短信内容

    在一些应用上,比如手机银行,QQ,微信等,很多时候我们都需要通过发送验证码到手机上,然后把验证码填上去,然后才能成功地继续去做下面一步事情. 而如果每次我们都要离开当前界面,然后去查收短信,记住验证码 ...

  2. 2017青岛网络赛1008 Chinese Zodiac

    Chinese Zodiac Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) T ...

  3. JAVAEE 是什么,如何获取各种规范jar包及各种规范的jar包源码

    1.什么是JAVA EE JAVA EE是由一系列规范组成的,规范是由JCP制定的,并且提供了参考实现.规范(Specification)是一系列接口,不包含具体实现 有以下常见的JAVA EE实现, ...

  4. jquery实现鼠标移入移除背景图片切换

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Objective-C设计模式——单例Singleton(对象创建)

    单例 和其它语言的单例产不多,可以说是最简单的一种设计模式了.但是有几个点需要注意下,单例就是一个类只有一个实例. 所以我们要想办法阻止该类产生别的实例,一般语言中都会将构造函数写为private.但 ...

  6. vscode使用教程(web开发)

    1.安装 进入官网下载https://code.visualstudio.com/ 一直下一步就好了,中间可以选择把软件安装在哪个目录. 2.常用插件安装 a. 进入扩展视图界面安装/卸载 a1.快捷 ...

  7. 【Android学习笔记】Mac下Android Studio开发环境搭建

    本文由@ray 出品,转载请注明出处.  文章链接:http://www.cnblogs.com/wolfray/p/7829069.html 对于移动端这块,笔者之前一直都是进行iOS开发的,也从来 ...

  8. Spartan6系列之GTP Transceiver的介绍与使用

    1.       什么是GTP transceiver? GTP transceiver是FPGA里一种线速度达500Mb/sà6.6Gb/s的收发器,利用FPGA内部可编程资源可对其进行灵活地配置, ...

  9. (独孤九剑)---PHP操作MySQL数据库

    [一]开启mysql扩展 在PHP操作MySQL数据库之前,要保证开启了MySQL数据库扩展 若未开启,则可以将php.int文件下的php_mysql开启即可,方式为去掉前面的封号; 配置完成后要重 ...

  10. react 返回上一页

    import * as React from 'react' import { Layout } from 'antd'; import creatHistory from 'history/crea ...