使用synchronized(非this对象)同步代码块解决脏读问题
首先通过示例来学习验证多个线程调用同一个方法时随机的。
package syn_out_asyn; import java.util.ArrayList;
import java.util.List; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class MyList {
private List list = new ArrayList();
synchronized public void add(String username){
System.out.println("ThreadName="+Thread.currentThread().getName()+"执行了add方法");
list.add(username);
System.out.println("ThreadName="+Thread.currentThread().getName()+"退出了add方法");
}
synchronized public int getSize(){
System.out.println("ThreadName= "+Thread.currentThread().getName()+"执行了getSize方法");
int sizeValue= list.size();
System.out.println("ThreadName= "+Thread.currentThread().getName()+"退出了getSize方法");
return sizeValue;
}
}
package syn_out_asyn; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadA extends Thread {
private MyList list;
public ThreadA (MyList list){
super();
this.list = list;
} public void run(){
for(int i=0;i<10000;i++){
list.add("ThreadA"+(i+1));
}
}
}
package syn_out_asyn; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadB extends Thread {
private MyList list;
public ThreadB(MyList list){
super();
this.list = list;
}
public void run(){
for(int i=0;i<10000;i++){
list.add("threadB"+(i+1));
}
}
}
package syn_out_asyn; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String[] args){
MyList myList = new MyList();
ThreadA threadA = new ThreadA(myList);
threadA.setName("A");
threadA.start();
ThreadB threadB = new ThreadB(myList);
threadB.setName("B");
threadB.start();
}
}
执行结果:
ThreadName=A执行了add方法
ThreadName=A退出了add方法
ThreadName=A执行了add方法
ThreadName=A退出了add方法
ThreadName=A执行了add方法
ThreadName=A退出了add方法
ThreadName=B执行了add方法
ThreadName=B退出了add方法
ThreadName=B执行了add方法
ThreadName=B退出了add方法
ThreadName=B执行了add方法
ThreadName=B退出了add方法
从结果来看,同步块中的代码是同步打印的,当前线程的执行和退出时成对出现的。但线程A和线程B的执行却是异步的,这就有可能出现脏读的环境。由于线程执行的方法的顺序不确定,所以当A和B两个线程执行带有分之判断的方法时,就会出现逻辑上的错误,有可能出现脏读。
package t9; import java.util.ArrayList;
import java.util.List; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class MyOneList {
private List list = new ArrayList();
synchronized public void add(String data){
list.add(data);
}
synchronized public int getSize(){
return list.size();
}
}
package t9; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class MyService {
public MyOneList addServiceMethod(MyOneList list ,String data) {
try {
if (list.getSize() < 1) { Thread.sleep(2000);//模拟从远程话费2秒取回数据
list.add(data);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
}
package t9; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class MyThread1 extends Thread {
private MyOneList list;
public MyThread1(MyOneList list){
super();
this.list=list;
}
public void run(){
MyService myService = new MyService();
myService.addServiceMethod(list,"A");
}
}
package t9; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class MyThread2 extends Thread {
private MyOneList list;
public MyThread2(MyOneList list){
super();
this.list=list;
}
public void run(){
MyService myService = new MyService();
myService.addServiceMethod(list,"B");
}
}
package t9; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class Run {
public static void main(String [] args) throws InterruptedException {
MyOneList list = new MyOneList();
MyThread1 thread1 = new MyThread1(list);
thread1.setName("A");
thread1.start();
MyThread2 thread2 = new MyThread2(list);
thread2.setName("B");
thread2.start();
Thread.sleep(6000);
System.out.println("listSize="+list.getSize());
}
}
运行结果:
listSize=2
脏读出现了,原因是两个线程以异步的方式返回list参数的size()大小,解决的办法就是同步化。
修改MyService.java
package t9; /**
* Created by Administrator on 2017/1/20 0020.
*/
public class MyService {
public MyOneList addServiceMethod(MyOneList list ,String data) {
try {
synchronized (list) {
if (list.getSize() < 1) { Thread.sleep(2000);//模拟从远程话费2秒取回数据
list.add(data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
}
运行结果:
listSize=1
由于list参数对象在项目中是一份实例,是单例的,而且也正需要对list参数的getSize()方法做同步的调用,所以就对list参数进行同步处理。
结论:synchronized(非this对象x):格式的写法是将x对象本身作为“对象监视器”
使用synchronized(非this对象)同步代码块解决脏读问题的更多相关文章
- JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this
JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...
- Java的synchronized的同步代码块和同步方法的区别
synchronized同步方法和同步代码块的区别 同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不 ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
- synchronized同步方法和同步代码块的区别
同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不是整个方法. 同步方法使用synchronized修 ...
- Java之同步代码块处理继承Thread类的线程安全问题
package com.atguigu.java; /** *//** * 使用同步代码块解决继承Thread类的方式的线程安全问题 * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thre ...
- Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...
- 2016/9/25编写java实验报告时对synchronized(同步代码块)的一些感悟
通过此次实验,明白了多线程的设置和启动.synchronized代码块的用法.线程的优先级使用方法.知道了那几类资源是线程共享的. 我现在理解的多线程是:实例化一个继承了Thread类或实现了Runn ...
- 线程同步 synchronized 同步代码块 同步方法 同步锁
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- 彻底理解线程同步与同步代码块synchronized
public class Demo { public static synchronized void fun1(){ } public synchronized void fun2(){ } pub ...
随机推荐
- MVC教程三:URL匹配
1.使用{parameter}做模糊匹配 {parameter}:花括弧加任意长度的字符串,字符串不能定义成controller和action字母.默认的就是模糊匹配. 例如:{admin}. usi ...
- 02 Architecture Overview
本章提要---------------------------------------------arthiecture, and some componentconnect to oracle这一章 ...
- Windows 10恢复Shift+右键打开命令提示符窗口
导入以下注册表即可. Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\Background\shell\cmd1] ...
- 关于Struts2的action的execute方法
这个方法必须要有一个String类型的返回值,所以如果写很多if else的话,记得要在最后加一个else,就是无论如何就会放回一个字符串,否则编译会报错,在execute方法名字下面有红线.
- 【F12】修改 DevTools的主题
1.点击setting
- tensorflow中slim模块api介绍
tensorflow中slim模块api介绍 翻译 2017年08月29日 20:13:35 http://blog.csdn.net/guvcolie/article/details/77686 ...
- matplotlib中的legend()——用于显示图例
legend()的一个用法: 当我们有多个 axes时,我们如何把它们的图例放在一起呢?? 我们可以这么做: import matplotlib.pyplot as plt import numpy ...
- 获取作为 URL 部署清单的位置。
ActivationContext ac = AppDomain.CurrentDomain.ActivationContext; ApplicationIdentity ai = ac.Identi ...
- html中可以自定义属性,,,妈的竟然才知道..
html中可以自定义属性,,,妈的竟然才知道.. <input userinfo="没见过帅哥呀" />
- CleanMyMac 3.7.5最强中文版_激活码_破解版_下载_注册码
版权归作者所有,任何形式转载请联系作者.作者:缘来远去(来自豆瓣)来源:https://www.douban.com/note/612586476/ 最新版CleanMyMac 3中文版本已经发布快要 ...