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还是不够熟悉,有许多疑问,所有在网上找了很多文章看了一下,总体说的不够详细,重点和焦点问题没有谈到,但这篇文章相当不 ...
随机推荐
- js封装的三级联动菜单(使用时只需要一行js代码)
前言 在实际的项目开发中,我们经常需要三级联动,比如省市区的选择,商品的三级分类的选择等等. 而网上却找不到一个代码完整.功能强大.使用简单的三级联动菜单,大都只是简单的讲了一下实现思路. 下面就给大 ...
- CentOS安装Redis
wget http://download.redis.io/redis-stable.tar.gz tar xvzf redis-stable.tar.gz cd redis-stable make ...
- Python学习--Python简介
Python 简介 Python是一种解释型.编译性.面向对象.动态数据类型的高级程序设计语言.Python由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年. P ...
- poj2217
Secretary Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1257 Accepted: 515 Descript ...
- gg
纪念那段为了梦想的青春岁月,CS. Esp (2006-2014) name "Esp"bind "TAB" "+showscores"bi ...
- Data Binding使用技巧
Data Binding 根据变量,自动赋值到各widget. How 1.编写layout文件,这里的layout为: act_data_bind_demo.xml 这里需要先准备变量 在具体的wi ...
- [bigdata] 从Cloudera Manager中彻底删除服务器
1. 在CM中主机页里,选定要删除的服务器,选择操作“从群集中删除”. 2. 登录到主机,执行chkconfig,显示有cloudera-scm-agent服务, 执行service cloudera ...
- JSF primefaces dataTable paginator 表格分页 问题
当第一次查询返回list列表,分页1,2,3.....这是选择2,当前页面停留在第2页. 当再次查询后,因为使用的ajax,结果更新了,但当前页面依旧是第2页. 可以在jsf页面,datatable的 ...
- 【原创】自己动手写工具----签到器[Beta 2.0]
一.前面的话 上一篇中基本实现了简单的签到任务,但是不够灵活.在上一篇自己动手写工具----签到器的结尾中,我设想了几个新增功能来提高工具的灵活程度,下面把新增功能点列出来看看: (1)新增其他的进程 ...
- CSS3 border-image 属性
border-image 属性是一个简写属性,用于设置以下属性: border-image-source 用在边框的图片的路径,默认值none. 如:border-image-source:url(b ...