好久没有更新博客了,今天试着用简单的语言把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. PAT 1042. 字符统计(20)

    请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过1000的字符串.字符串由ASCII码表中任意可见字符及空格组成,至少包含1个英文字母,以回车结束( ...

  2. [LeetCode] Find Median from Data Stream 找出数据流的中位数

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  3. 编写轻量ajax组件01-对比webform平台上的各种实现方式

    前言 Asp.net WebForm 和 Asp.net MVC(简称MVC) 都是基于Asp.net的web开发框架,两者有很大的区别,其中一个就是MVC更加注重http本质,而WebForm试图屏 ...

  4. 【swift学习笔记】六.访facebook登录页面

    代码最下边有下载地址. 做这个demo的主要心得就是自适应所有的屏幕,要先布局大的框架,再一步一步设置小的细节. 看一下效果 再看一下自动适应所有屏幕的效果: keyboard打开时整个frame上移 ...

  5. Ubuntu apache2.4 设置虚拟主机

    每次重装系统如何配置都上网找,搞半天,都是不对的,还不如自己记下来,以作参考呢.我的项目目录是 /home/feiffy/demo/test,映射的域名是 test.com,这样在浏览器输入 test ...

  6. 常用Linux命令

    1.mkdir 建立目录 $ mkdir testdir 2.ls   列出目录下的内容的详细信息  ls -al testdir 3.cd  更换当前工作目录   cd testdir 4.pwd  ...

  7. 浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法(转载)

    在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们发现程序执行完后并没有获取到我们想要的值,这时很有可能是因为你用的是ajax的异步调用async:t ...

  8. localForage——轻松实现 Web 离线存储(转)

    localStorage 能够让你实现基本的数据存储,但它的速度慢,而且不能处理二进制数据.IndexedDB 和 WebSQL 是异步的,速度快,支持大数据集,但他们的API 使用起来有点复杂.不仅 ...

  9. 架构师养成记--10.master-worker模式

    master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...

  10. CentOS7清理yum缓存和释放内存方法

    清理yum缓存 清理yum缓存使用yum clean 命令,yum clean 的参数有headers, packages, metadata, dbcache, plugins, expire-ca ...