14_synchronized深入
【脏读】
对于对象同步和异步的方法,我们在设计程序的时候,一定要考虑问题的整体,不然会出现不一致的错误,最经典的错误的就是脏读(dirty read)。
【实例代码】
package com.higgin.part4; /**
* 在我们对一个对象的方法加锁的时候,需要考虑业务的整体性。
* 本例子中的setValue或getValue必须同时加上synchronized同步关键字,办证业务的原子性,不然会出现业务错误
*/
public class DirtyRead {
private String username="zhangsan";
private String password=""; public synchronized void setValue(String username,String password){
this.username=username;
try {
Thread.sleep(); //延时2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
this.password=password;
System.out.println("setValue最终结果【 username = "+username+", password = "+password + "】");
} /**
* 加和不加synchronized有区别
*/
public void getValue(){
System.out.println("getValue最终结果【 username = "+username+", password = "+password + "】");
} public static void main(String[] args) throws InterruptedException {
final DirtyRead dr = new DirtyRead(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
dr.setValue("lisi", "");
}
});
t1.start(); //t1线程去设置值
Thread.sleep();
dr.getValue(); //相当于main线程去读取值
}
}
【运行结果:不加synchronized】

【运行结果:加上synchronized】

【关于synchronized代码块】
直接使用synchronized声明的方法是在有些情况下是有弊端的,比如A线程调用的同步方法执行一个时间很长的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下可以使用synchronized代码块去优化代码执行时间,也就是通常所说的减小锁的粒度。
【synchronized代码块加锁:对象锁、类锁、任意对象锁】
package com.higgin.part6;
public class DiffLock {
public void method1(){
synchronized(this){ //对象锁
System.out.println("method1");
}
}
public void method2(){
synchronized(DiffLock.class){ //类锁
System.out.println("method2");
}
}
private Object obj = new Object();
public void method3(){
synchronized(obj){ //任意对象锁
System.out.println("method3");
}
}
}
【关于String类型的锁】
注意不要使用String的常量加锁,容易出现死循环问题。
package com.higgin.part6; /**
* synchronized代码块对字符串的锁,注意String常量池的缓存功能
*/
public class StringLock { public void method() {
//分别使用new String("abc")和"abc"
synchronized ("abc") { //这里是一个String类型的常量锁
try {
while(true){
System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
Thread.sleep();
System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
final StringLock stringLock = new StringLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
stringLock.method();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
stringLock.method();
}
},"t2"); t1.start(); //这里本质上t1、t2抢占的是同一个String锁("abc"),t1一直未释放锁,导致t2无法获得锁执行代码
t2.start();
}
}
【运行结果:使用"abc"常量字符串作为锁,t2线程一直无法执行】

【运行结果:使用new String("abc")非常量字符作为锁,t2和t1竞争执行】

14_synchronized深入的更多相关文章
随机推荐
- Android TCP协议的Socket通信
1.介绍 2.使用方法 3.java后台代码 服务器server package com.lucky.servertest; import java.io.BufferedReader; import ...
- 【算法笔记】B1027 打印沙漏
1027 打印沙漏 (20 分) 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输出奇 ...
- Visual Studio Ultimate 2013 免费下载地址
ed2k://|file|cn_visual_studio_2010_ultimate_x86_dvd_532347.iso|2685982720|4AE6228933DDE49D9BFA4C3467 ...
- Codeforces 1136D Nastya Is Buying Lunch (贪心)
题意: 给一个序列和一组交换序列(a,b),当且仅当a在b的前面(不允许有间隔),这两个数才能交换,问最后一个数最多能移动多少个位置. 分析: 这题是思路是十分的巧妙呀 , 用一个数组num[x] ...
- Ubuntu 15.04 下apt-get安装JDK
[From] http://blog.csdn.net/skykingf/article/details/45250017 1.删除自带的OpenJDK [python] view plain cop ...
- PIE SDK分类统计
1. 算法功能简介 分类统计功能是将分类后的结果统计输出. PIE SDK支持算法功能的执行,下面对分类统计算法功能进行介绍. 2. 算法功能实现说明 2.1. 实现步骤 第一步 算法参数设置 第二步 ...
- python练习六十九:urllib爬取练习
爬取图片,将链接中的图片取出来,并统计一共下载了多少图片 代码: def fetch_pictures(url): headers = {'User-Agent':'Mozilla/5.0 (Wind ...
- centos7.3下安装redis3.2 yum安装
1.进入centos 2.运行:yum install redis 3.安装完成后,选择y,确认 4.进入:cd /etc/;vi redis.conf 将,daemonize 修改为yes,并且添加 ...
- 2019.03.28 读书笔记 关于lock
多线程就离不开lock,lock的本质是一个语法糖,采用了监视器Monitor. lock的参数,错误方式有很多种,只需要记住一种:private static readonly object loc ...
- 一些Andoid studio常用的快捷键
常用快捷键 Android Studio是基于IntelliJ IDEA的,我们都知道,IDEA是一个很方便很好用的IDE,其中有许多快捷键,但是太多快捷键我们也记不住. 其实,我们可以记住几个 ...