synchronized使用说明
好久没有更新博客了,今天试着用简单的语言把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使用说明的更多相关文章
- [转]Java 对象锁-synchronized()与线程的状态与生命周期
线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){ //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...
- java线程同步以及对象锁和类锁解析(多线程synchronized关键字)
一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...
- Atitit.项目修改补丁打包工具 使用说明
Atitit.项目修改补丁打包工具 使用说明 1.1. 打包工具已经在群里面.打包工具.bat1 1.2. 使用方法:放在项目主目录下,执行即可1 1.3. 打包工具的原理以及要打包的项目列表1 1. ...
- awk使用说明
原文地址:http://www.cnblogs.com/verrion/p/awk_usage.html Awk使用说明 运维必须掌握的三剑客工具:grep(文件内容过滤器),sed(数据流处理器), ...
- java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...
- 单例模式中用volatile和synchronized来满足双重检查锁机制
背景:我们在实现单例模式的时候往往会忽略掉多线程的情况,就是写的代码在单线程的情况下是没问题的,但是一碰到多个线程的时候,由于代码没写好,就会引发很多问题,而且这些问题都是很隐蔽和很难排查的. 例子1 ...
- Thread 学习记录 <1> -- volatile和synchronized
恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1; ...
- 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...
- (转)Lock和synchronized比较详解
今天看了并发实践这本书的ReentantLock这章,感觉对ReentantLock还是不够熟悉,有许多疑问,所有在网上找了很多文章看了一下,总体说的不够详细,重点和焦点问题没有谈到,但这篇文章相当不 ...
随机推荐
- thrift:swift项目笔记
先声明:此swift不是Apple公司的那个swift开发语言,而是facebook的另一个开源项目. facebook的thrift IDL文件,如果默认用thrift -gen java生成jav ...
- MATLAB 成对T检验(paired-ttest)
学过的统计知识忘光了,飞速恶补了一下能用到的,此篇多有错误今后看到再改= =||| 成对t检验(Paired ttest) 将两组测量值对应相减,再将所得差值看作服从正态分布的随机变量,然后再做关于差 ...
- dubbo 配置解析
1.dubbo 常用配置 <dubbo:service/> 服务配置,用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心.eg.<dub ...
- UIButton快速点击,只执行最后一次
button快速点击时,会导致,同一动作执行多次,常用解决办法: 第一种方法:推荐 //取消执行 [[self class] cancelPreviousPerformRequestsWithTarg ...
- Django session cookie 上传文件、详解
session 在这里先说session 配置URL from django.conf.urls import patterns, include, url from django.contrib i ...
- form表单提交时,action怎么带参数
<html> <title>form</title> <script type="text/javascript"> functio ...
- my computer
把08年买的电脑换了,自己买的配件装的,狂拽酷炫叼炸天. 配置清单: CPU :英特尔至强E3-1230 V2 主板 :华硕P8Z77-V LX LX2 机箱 :撒哈拉海盗贼王Z6游戏机箱(白色限量版 ...
- java中关键字volatile的作用
用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...
- 北京培训记day5
高级数据结构 一.左偏树&斜堆 orz黄源河论文 合并,插入,删除根节点 打标记 struct Node { int fa,l,r,w,dep } tree[Mx]; int Merge(in ...
- Javascript中两个等于号和三个等于号的区别(==/===)
==//表示值的比较 ===//表示对象类型的比较 1.对于string,number等基础类型,==和===是有区别的. a)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,== ...