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深入的更多相关文章
随机推荐
- SqlBulkCopy使用注意事项
1. 有标识列的表 1.1 SqlBulkCopyOptions.KeepIdentity 必须设置!否则会出现复制过去的数据产生标识列发现变化的情况! 1.2 如果原表的标识列即为主键, 那按1. ...
- [USACO08DEC]拍头Patting Heads 数学 BZOJ 1607
题目描述 It's Bessie's birthday and time for party games! Bessie has instructed the N (1 <= N <= 1 ...
- WPF:CheckBox竖向的滑块效果
原文:WPF:CheckBox竖向的滑块效果 之前做了一个横向的滑块效果,<WPF:CheckBox滑块效果>,其实我觉得那个不好看,今天又做了一个竖向的玩. <Style Targ ...
- .Net Core 使用swagger UI
swagger UI 第一步:首先添加包Swashbuckle.AspNetCore (可通过微软添加包命令Install-Package 包名进行添加,也可以通过管理NuGet程序包进行添加) 第二 ...
- python---day14( 内置函数二)
内置函数二一:匿名函数 lambda函数 lambda 表示匿名函数,不需要用def 来申明. 语法: 函数名=lambda 参数:返回值 ----〉 案例:f=lambda n:n*n 例子01: ...
- Scala 中 for 循环 和 generator 的使用例子
这个例子是,从每个list中,找到age最大的那个node. class Node(vName: String, vAge: Int) { // Entity class var name: Stri ...
- 解决运行vue项目的报错This relative module was not found:
运行vue项目出现这样的报错. This relative module was not found: * ../../assets/img/spot.png !./src/components/on ...
- linux 密码复杂度设置
/etc/login.defs文件,里面几个选项 PASS_MAX_DAYS 90 #密码最长过期天数 PASS_MIN_DAYS 80 #密码最小过期天数 PASS_MIN_LEN 10 #密码最小 ...
- MHA 高可用架构部署
一, MHA 介绍 MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公 ...
- Ba Gua Zhen
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5544 学习链接:https://www.cnblogs.com/qscqesze/p/4902518. ...