synchronized这个关键字想必学Java的人都应该知道。

直接上例子:

方法级别实例

public class AtomicInteger {

    private int index;

    public synchronized int addAndGet() {
try {
Thread.sleep(2000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ++ index;
} public int get() {
return index;
} }

一个自动增长的类,不解释了。

看测试代码:

final AtomicInteger ai = new AtomicInteger();

new Thread(new Runnable() {
@Override
public void run() {
ai.addAndGet();
System.out.println("thread1 finish sleep");
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
ai.addAndGet();
System.out.println("thread2 finish sleep");
}
}).start();

这里例子执行结果是这样的:

过2秒,输出thread1 finish sleep

然后再过2秒,输出thread2 finish sleep。

现在我们把AtomicInteger类里的addAndGet方法前的synchronized关键字去掉。

执行结果是这样的:

过2秒,输出  thread1 finish sleep  然后马上输出  thread2 finish sleep (可能先输出thread2 finish sleep)

分析

java中synchronized就是"加锁"的意思, 一个实例中的方法如果加上了synchronized,那么这个方法如果被调用了,就会自动加上一个锁,如果其他线程想要再次调用这个实例的这个方法,那么需要等待之前的线程执行完成之后才能执行。

因此,之前的实例方法之前有synchronized的执行结果就是过2秒输出一段,再过2秒再次输出。

类级别实例

下面。 我们给AtomicInteger加一个静态同步方法。

public static synchronized void sync() {
System.out.println("now synchronized. wait 4 seconds.");
try {
Thread.sleep(2000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

测试代码:

final AtomicInteger ai = new AtomicInteger();

AtomicInteger.sync();

new Thread(new Runnable() {
@Override
public void run() {
ai.addAndGet();
System.out.println("thread1 finish sleep");
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
ai.addAndGet();
System.out.println("thread2 finish sleep");
}
}).start();

这个测试结果执行结果是这样的:

先输出  now synchronized. wait 4 seconds.

过4秒(因为静态同步方法需要2秒,addAndGet方法也需要2秒),输出 thread1 finish sleep

再过2秒,输出 thread2 finish sleep

分析

从上述类级别的实例可以看出  ->   静态同步方法作用的范围是类,执行了静态同步方法,静态同步方法执行的时候,这个类中的所有方法(无论是否有synchronized, 无论是否静态)都必须等待这个静态同步方法执行完成之后才能进行

如果我们把AtomicInteger的addAndGet方法的synchronized关键字去掉,那么执行结果是这样的。

先输出  now synchronized. wait 4 seconds.

过4秒,输出 thread1 finish sleep

然后马上又输出 thread2 finish sleep

再来看个例子:

final AtomicInteger ai1 = new AtomicInteger();
final AtomicInteger ai2 = new AtomicInteger(); AtomicInteger.sync(); new Thread(new Runnable() {
@Override
public void run() {
ai1.addAndGet();
System.out.println("ai1 finish sleep");
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
ai2.addAndGet();
System.out.println("ai2 finish sleep");
}
}).start();

执行结果是这样的。

先输出  now synchronized. wait 4 seconds.

过4秒,输出 ai1 finish sleep

然后马上又输出 ai2 finish sleep

小结: 由于静态同步方法是作用于类级别的,因此实例级别的方法调用都收到影响。所以执行AtomicInteger.sync();的时候ai1,ai2都在等待。 当执行完毕的时候,ai1和ai2由于是不同实例,方法级别的synchronized当然互不影响。

资源级别的实例

资源级别的同步其实跟方法级别的同步是一样的,只不过资源级别的同步的作用更加细节一下,它作用的对象是基于资源的。比如实例中的成员变量。

死锁,可以完美说明资源级别的同步。

public class DeadLock {

    private static Object obj1 = new Object();
private static Object obj2 = new Object(); public static void main(String[] args) {
new Thread(new SubThread1()).start();
new Thread(new SubThread2()).start();
} private static class SubThread1 implements Runnable {
@Override
public void run() {
synchronized (obj1) {
try {
Thread.sleep(1000l);
System.out.println("thread1 synchronized obj1 and wait for obj2.");
synchronized (obj2) {
System.out.println("thread1 synchronized obj2");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} private static class SubThread2 implements Runnable {
@Override
public void run() {
synchronized (obj2) {
try {
Thread.sleep(1000l);
System.out.println("thread2 synchronized obj2 and wait for obj1.");
synchronized (obj1) {
System.out.println("thread2 synchronized obj1");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} }

从死锁这个实例可以看出。

子线程1同步obj1资源的时候,其他线程是不能获得obj1这个资源的。同理,子线程同步obj2资源的时候,其他线程是不能获得obj2这个资源的。

因此,子线程1在同步obj1之后,会等待obj2的释放(obj2已经被子线程2同步了,子线程1不能获得);而子线程2在同步obj2之后,会等待obj1的释放(obj1已经被子线程1同步了,子线程2不能获得)。

所以,这个程序将永远地等待下去。 这也就是著名的死锁问题。

我们可以通过jdk提供的一些命令查看是否死锁。

首先通过jps查看当前jdk启动的进程。

找到死锁这个程序的进程号6552之后再通过  jstack -l 6552 查看堆栈信息。

看到jstack发现了一个死锁。

总结

synchronized关键字可以作用在多个场景之下,我们需要区分清楚各个场景的区别,以便我们设计出符合高并发的程序。

之前对java并发这块了解的太少了.. 面试的时候也问到这些问题,发现自己根本答不上来。

java synchronized关键字浅析的更多相关文章

  1. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  2. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  3. Java synchronized关键字用法(清晰易懂)

    本篇随笔主要介绍 java 中 synchronized 关键字常用法,主要有以下四个方面: 1.实例方法同步 2.静态方法同步 3.实例方法中同步块 4.静态方法中同步块 我觉得在学习synchro ...

  4. java synchronized关键字浅探

    synchronized 是 java 多线程编程中用于使线程之间的操作串行化的关键字.这种措施类似于数据库中使用排他锁实现并发控制,但是有所不同的是,数据库中是对数据对象加锁,而 java 则是对将 ...

  5. java synchronized关键字

    引用其他人的一段话 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchro ...

  6. Java synchronized关键字的理解

    转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ...

  7. [java] java synchronized 关键字详解

    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一 ...

  8. Java:synchronized关键字引出的多种锁

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这 ...

  9. java synchronized关键字的底层实现

    每个对象都有一个锁(Monitor,监视器锁),class对象也有锁,如果synchronized关键字修饰同步代码块,通过反编译可以看到,其实是有个monitorenter和monitorexit指 ...

随机推荐

  1. WebX框架的页面授权

    WebX框架的页面授权 什么是页面授权,简单来说就是对于一个Web应用程序里,哪些页面可以被哪些人在什么情况下访问进行限制.举个简单的例子,有些页面只有用户登录以后才能访问,而另外一些页面无论是否用户 ...

  2. RMAN 与control文件和spfile文件的备份

    以10.2为例,官方文档如此说: http://docs.oracle.com/cd/B19306_01/backup.102/b14191/rcmconc1.htm The RMAN behavio ...

  3. AGC 007 D - Shik and Game

    D - Shik and Game 链接 题意: 数轴上有一个人,从0出发到E,速度为1.数轴上还有n只熊,每只熊会在经过后的T时刻后产生一个金币.给定E,T以及n个熊的坐标pi,求收集完所有金币并到 ...

  4. idea tomcat 热部署方法

    https://jingyan.baidu.com/article/db55b609d2a1564ba20a2f61.html 还好有热部署,不然每次都要重启服务,实在是太浪费时间了~ 注意事项: 在 ...

  5. How to implement a custom PropertyEditor so that it supports Appearance rules provided by the ConditionalAppearance module

    https://www.devexpress.com/Support/Center/Question/Details/T505528/how-to-implement-a-custom-propert ...

  6. IVF link error错误不显示的问题

      遇到一个奇怪的问题,IVF编译链接时显示error LINK: 后面没有具体的错误信息(见后图,我的窗口后面是空的)环境:windows 10 64位系统,VS2017 commutity 版本, ...

  7. MySQL事务及其实现

    事务定义 事务是访问并更新数据库中各个数据项的一个程序执行单元.在事务操作中,要不都做修改,要么都不做. 事务特性 事务具有ACID四个特性,分别是:原子性(Atomicity).一致性(Consis ...

  8. 最安全的聊天工具——Cryptocat

    关于Cryptocat Cryptocat 是啥?Cryptocat,俗称 "加密猫",是一款非常注重安全的聊天软件. 美国前中情局员工斯诺登在躲避美国政府追捕过程中,就是使用 C ...

  9. node安装和npm全局配置

    本文章环境 windows10 64位家庭版 Node10.15.3LTS 安装包下载 Node官网 安装node 点击安装文件, 一键安装, 注意安装位置和添加到环境变量(xx to PATH)选项 ...

  10. 表格 - bootStrap4常用CSS笔记

    [表格标签]   <table> 定义一个表格 <thead> 表格表头 <tbody> 表格主体内容 <tr> 行 <th> 表头列 &l ...