好久没有更新博客了,今天试着用简单的语言把synchronized的使用说清楚。

synchronized是什么?

synchronized是用来保证在多线程环境下代码同步执行的可重入的互斥锁。所谓互斥锁是指锁一旦被某个线程拿到之后,其他线程就无法获取锁,只能等到持有锁的线程的释放之后重新尝试获取。至于可重入,则是指已经获取到锁的那个线程在访问加锁代码块的时候是不需要重新获取锁的,可以直接执行代码块,在稍后的例子中也会有这样的测试代码来验证这一点。

synchronized怎么用?

synchronized有两种使用方式:

1、作用于方法声明处;

public synchronized void test() {
// code here...
}

2、作用于代码块。

public void test() {
// 1. 锁只针对当前对象
synchronized(this) {
// code here...
}
// 2. 针对某一个对象加锁
synchronized(obj) {
// code here...
}
// 3. 针对某一个类加锁
synchronized(XXX.class) {
// code here...
}
}

如果方法内部的代码全部在synchronized(this){}中的话,作用是与第一种方式等价的,内部实现是否一样,这个就不得而知了。

对没有声明锁的方法,或者代码块,不会受到锁的限制的。

死锁

所谓死锁用最简单的话描述就是,两个线程互相持有对方的需要的锁形成的一种僵持状态。比如线程A持有锁Y,等线程B释放锁X,而线程B持有锁X,等线程A释放锁Y。可以通过jstack检测死锁相关问题。避免死锁的发生,需要线程按照顺序获取需要的锁,避免形成竞争。说来简单,coding的时候还要主动注意才行。

synchronized 和 ReentrantLock

两者都是可重入的互斥锁,在语义上可以认为是一样的。区别就是synchronized自动获取锁,执行完毕后自动释放锁,为代码编码带来了较大的便利,同时因为这种便利,也失去灵活性。我们无法控制尝试加锁、主动解锁的场景,ReentrantLock则提供了这种方法的使用,而ReentrantLock的就需要自己来释放锁了,锁一定要放在finally代码块里释放,否则。。。哼哼

测试代码

public class TestSynchronized {

    public static void main(String[] args) throws InterruptedException {
byte[] lock = new byte[0];
final MyRunnable runnable1 = new MyRunnable();
final MyRunnable runnable2 = new MyRunnable();
Thread thread1 = new Thread(runnable1);
thread1.start();
Thread thread2 = new Thread(runnable2);
thread2.start(); // 保证上面的线程先start
Thread.sleep(100L); new Thread(new Runnable() {
@Override
public void run() {
runnable1.testCall();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
runnable2.testCall();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
runnable1.testCall2();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
runnable2.testCall2();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
runnable1.testCall3();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
runnable2.testCall3();
}
}).start(); Thread thread3 = new Thread(new MyLockRunnable(lock));
thread3.start(); Thread thread4 = new Thread(new MyLockRunnable(lock));
thread4.start(); Thread thread7 = new Thread(new MysynchronizedClassRunnable());
thread7.start(); Thread thread8 = new Thread(new MysynchronizedClassRunnable());
thread8.start(); } public static class MyRunnable implements Runnable {
// 防止测试可重入的时候陷入无限递归
boolean testIn = false;
@Override
public void run() {
// 锁只针对当前对象
synchronized (this) {
System.out.println(this.getClass().getName());
// 可重入测试
if (!testIn) {
testIn = true;
this.run();
}
while (true) {}
}
} // 因为run方法一直持有当然对象,所以这个方法永远获取不到锁。
public void testCall() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " testCall...");
}
}
// 等价于上面的testCall方法,锁定代码块,只不过这个是锁定的方法级别的代码块
public synchronized void testCall2() {
System.out.println(Thread.currentThread().getName() + " testCall2...");
} // 非锁定方法,可以正常调用
public void testCall3() {
System.out.println(Thread.currentThread().getName() + " testCall3...");
}
} public static class MyLockRunnable implements Runnable {
private final byte[] lock;
MyLockRunnable(byte[] lock) {
this.lock = lock;
} @Override
public void run() {
// 针对所有引用这个lock对象的方法
synchronized (lock) {
System.out.println(this.getClass().getName());
while (true) {}
}
}
} public static class MysynchronizedClassRunnable implements Runnable {
@Override
public void run() {
// 针对这个这个class加锁
synchronized (this.getClass()) {
System.out.println(this.getClass().getName());
while (true) {}
}
}
}
}

synchronized使用说明的更多相关文章

  1. [转]Java 对象锁-synchronized()与线程的状态与生命周期

      线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){   //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...

  2. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

  3. Atitit.项目修改补丁打包工具 使用说明

    Atitit.项目修改补丁打包工具 使用说明 1.1. 打包工具已经在群里面.打包工具.bat1 1.2. 使用方法:放在项目主目录下,执行即可1 1.3. 打包工具的原理以及要打包的项目列表1 1. ...

  4. awk使用说明

    原文地址:http://www.cnblogs.com/verrion/p/awk_usage.html Awk使用说明 运维必须掌握的三剑客工具:grep(文件内容过滤器),sed(数据流处理器), ...

  5. java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解

    synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...

  6. 单例模式中用volatile和synchronized来满足双重检查锁机制

    背景:我们在实现单例模式的时候往往会忽略掉多线程的情况,就是写的代码在单线程的情况下是没问题的,但是一碰到多个线程的时候,由于代码没写好,就会引发很多问题,而且这些问题都是很隐蔽和很难排查的. 例子1 ...

  7. Thread 学习记录 <1> -- volatile和synchronized

    恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1;  ...

  8. 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition

    img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...

  9. (转)Lock和synchronized比较详解

    今天看了并发实践这本书的ReentantLock这章,感觉对ReentantLock还是不够熟悉,有许多疑问,所有在网上找了很多文章看了一下,总体说的不够详细,重点和焦点问题没有谈到,但这篇文章相当不 ...

随机推荐

  1. 基于pcDuino-V2的无线视频智能小车 - pcduino上的网络编程

    通过获取从串口发送上来的数据  已经和上位机的连接通信和图像发送.已经对设备的控制 https://github.com/qq2216691777/pcduino_smartcar-pcduino

  2. JQuery中$.ajax()方法参数详解 及 async属性说明

    url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 ...

  3. Python学习进程

    1周第1天 主要是变量的学习(11月8日) 1.1 python安装(win和linux下)1.2 ipython安装及使用1.3 变量的定义1.4 变量赋值1.5 运算符(赋值.算术.关系.逻辑)1 ...

  4. jpa+springmvc+springdata(一)

    学习尚硅谷笔记: 首先配置application.xml: <?xml version="1.0" encoding="UTF-8"?> <b ...

  5. VS 生成事件

    转载自: http://hi.baidu.com/gisince/item/7f0439ee610c94255a2d64b4 今天写了生成事件的处理,如下: 从网上Down了一个例子,运行时提示错误 ...

  6. 迁移 SQL Server 数据库到 Azure SQL 实战

    最近有个维护的项目需要把 SQL Server 2012 的数据库迁移到 Azure SQL 上去,迁移过程可谓一波三折,故在此分享这次迁移中碰到的点点滴滴,希望对朋友们有所帮助. 文章来源:葡萄城产 ...

  7. 如何将本地项目与coding.net/github上的项目绑定

      得到coding.net/github项目的ssh协议地址 形如:·git@git.coding.net:wzw/leave-a-message.git· 在本地生成公钥 输入 ssh-keyge ...

  8. idea 如何隐藏/展示不想看到的文件

    隐藏:在 Ignore files and folders中添加想要过滤的文件或文件夹名称 展示隐藏文件: 在过滤列表中删除掉文件或者文件夹就好了

  9. mysql命令

    create 创建数据库 show databases 显示所有数据库 drop database 删除数据库 use 使用(进入)数据库 select 当前使用的数据库 create table 创 ...

  10. Java集合框架List,Map,Set等全面介绍

    Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I]   +--java.util.ArrayList [C]   +- ...