使用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 ...
随机推荐
- win7 64位安装oracle10g客户端心得
用了整整两天时间才在64位Win7下装好了Oracle的开发环境(包括Oracle的客户端和第三方客户端工具),过程原来和32位类似,注意不能下载64位的安装包. 安装过程: 1.下载Oracle 1 ...
- Tslib步骤以及出现问题的解决方案(转)
嵌入式设备中触摸屏使用非常广泛,但触摸屏的坐标和屏的坐标是不对称的,需要校准.校准广泛使用的是开源的tslib. Tslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波.去抖.校准等功能, ...
- EasyUI效果--DataGrid的编辑效果
DataGrid的编辑效果是我目前使用的easyUI的第三个效果,相对于前两个,这个算是比较复杂点了. 运行起来的效果,大概就是这样,任意点击某行,然后该行变为可以编辑的,失去焦点之后,该行恢复 ...
- 关于Cocos2d-x中地图轮播的实现
播放背景,两个背景的图片是一样的,紧挨着循环播放,以下代码写在playBackground()方法中,并在GameScene.cpp的init方法中调用. void GameScene::playBa ...
- Java JNI初探
---说明,之前直接百度出来的例子,照猫画虎.没想到的是这例子居然直接来自百度百科,写着写着就囧了.. ---anyway,写完了就当是给自己看吧. 同事求助,就看了一下,照猫画虎一番,略有所得. J ...
- PHP 初学之登录查询小case
说明:如误入本文,请忽略即可,内容仅为记录. 功能:登录(不验证),查询所有列表,删除记录.--很简单,仅为熟悉代码. // MySQL,新建数据库data,导入如下sql ; -- -------- ...
- 第二百九十四节,Redis缓存-Redis安装
redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sor ...
- linux -- Apache执行权限
最近在用php调用exec方法去执行一个linux终端下的命令,结果每次都不能执行成功,网上多番搜寻,最终找到一篇有用的文章,主要原因是因为Apache的执行权限的问题.以下是原文(稍加修改): 利用 ...
- R语言中两个数组(或向量)的外积怎样计算
所谓数组(或向量)a和b的外积,指的是a的每个元素和b的每个元素搭配在一起相乘得到的新元素.当然运算规则也可自己定义.外积运算符为 %o%(注意:百分号中间的字母是小写的字母o).比如: > a ...
- 页面的checkbox框的全选与反选
if (typeof jQuery == 'undefined') { alert("请先导入jQuery");} else { jQuery.extend({ ...