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深入的更多相关文章
随机推荐
- nuget服务器搭建
本文章主要介绍如何将本地dll打包成为一个Nuget包,并如何发布到自己的nuget服务器,示例代码下载.章节如下 1. 本地dll如何打包,以及版本的更新 2. 在linux上搭建nuget.ser ...
- [Error] ISO C++ forbids comparison between pointer and integer
错误代码: if(a[i]=="G"&&b[i]!="C") return false; 改正后的代码: if(a[i]=='G'&&a ...
- 二 ASP.NET MVC 第一个程序 hello world
二 ASP.NET MVC 第一个程序 hello world https://blog.csdn.net/xmroom/article/details/51335917 我使用的Visual s ...
- LeetCode231.2的幂
231.2的幂 描述 给定一个整数,编写一个函数来判断它是否是 2 的幂次方. 示例 示例 1: 输入: 1 输出: true 解释: 2^0 = 1 示例 2: 输入: 16 输出: true 解释 ...
- Linux 安装 Djiango
yum 安装方法 以下安装位于 Centos Linux 环境下安装,如果是你的 Linux 系统是 ubuntu 请使用 apt-get 命令. 默认情况下 Linux 环境已经支持了Python. ...
- gym101201F Illumination 2-SAT
题目传送门 题目大意: 给出n*n的网格,l栈灯,每盏灯可以选择照亮竖着的2*r+1的范围,或者横着的2*r+1的范围,要求一个格子不会同时被一盏以上的横着的灯照亮,也不能被一盏以上的竖着的灯照亮,所 ...
- Oracle笔记-Multitable INSERT 的用法
[转自] http://blog.chinaunix.net/uid-8504518-id-3310531.html 为避免日趋衰退的记忆力,参考官方E文文档<Introduction to ...
- nginx+uwsgi+virtualenv+supervisor部署项目
一.导论 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收请求,处理请求,响应请求) 基于wsgi运行的 ...
- TensorFlow-简单的卷积神经网络
先弄懂卷积神经网络的原理,推荐这两篇博客:http://blog.csdn.net/yunpiao123456/article/details/52437794 http://blog.csdn. ...
- [转]创建节约内存的JavaBean
转自:创建节约内存的JavaBean 如果编写节约内存的java对象 编写Java代码的时候,大多数情况下,我们很少关注一个Java对象究竟有多大(占据多少内存),更多的是关注业务与逻辑.但是殊不知, ...