首先通过示例来学习验证多个线程调用同一个方法时随机的。

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对象)同步代码块解决脏读问题的更多相关文章

  1. JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

    JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...

  2. Java的synchronized的同步代码块和同步方法的区别

    synchronized同步方法和同步代码块的区别 同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不 ...

  3. java中的synchronized同步代码块和同步方法的区别

    下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...

  4. synchronized同步方法和同步代码块的区别

    同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不是整个方法. 同步方法使用synchronized修 ...

  5. Java之同步代码块处理继承Thread类的线程安全问题

    package com.atguigu.java; /** *//** * 使用同步代码块解决继承Thread类的方式的线程安全问题 * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thre ...

  6. Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)

    关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...

  7. 2016/9/25编写java实验报告时对synchronized(同步代码块)的一些感悟

    通过此次实验,明白了多线程的设置和启动.synchronized代码块的用法.线程的优先级使用方法.知道了那几类资源是线程共享的. 我现在理解的多线程是:实例化一个继承了Thread类或实现了Runn ...

  8. 线程同步 synchronized 同步代码块 同步方法 同步锁

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  9. 彻底理解线程同步与同步代码块synchronized

    public class Demo { public static synchronized void fun1(){ } public synchronized void fun2(){ } pub ...

随机推荐

  1. kubernetes 阿里云安装(kubeadm方式)

    注意:不能修改hostnamecurl -sSL http://aliacs-k8s.oss-cn-hangzhou.aliyuncs.com/installer/kubemgr-1.6.1.sh & ...

  2. 六步破解win2008R2登录密码

    防火墙没有开启,win2008R被当成矿机,只好重新破解密码进去解决问题,试了好多方法,下列方法绝对实用简单. 破解2008登录密码的方法: 1.进入PE2.找到文件:windows\system32 ...

  3. 【mybase】绿色版---mybase非常好用的笔记软件

    mybase绿色软件,体积小,解压可以直接使用,PC端非常好用的笔记软件. 包含两个版本: mybase6.5.0 mybase7.0.0 软件下载地址: 链接: http://pan.baidu.c ...

  4. UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串

    链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...

  5. mysql慢查询日志开启和存储格式

    mysql版本号是mysql5.6.22.安装环境windows7. 1.使用该查询日志能够找到有效率问题的sql语句.并记录下来,进行监控. 能够使用例如以下语句查询和设置慢查询日志 (1) 查看慢 ...

  6. 【甘道夫】通过Mahout构建贝叶斯文本分类器案例具体解释

    背景&目标: 1.sport.tar 是体育类的文章,一共同拥有10个类别.    用这些原始材料构造一个体育类的文本分类器,并測试对照bayes和cbayes的效果:    记录分类器的构造 ...

  7. Graphviz 对网状结构进行可视化

    Graphviz 是一款开源的,免费的图结构的可视化软件,只需要描述清楚图中的顶点,边的信息,Graphviz 可以自动化的对图进行布局,生成对应的图片: Graphviz 采用DOT 的这种语言来描 ...

  8. navicat上如何导出视图,函数等

    如何导出视图,函数,一般通过linux命令行,如果简单点就用navicat把. image.png 这样函数,视图都可以导出来后续更新.....

  9. mui自定义事件带参返回mui.back()

    父页面添加自定义监听事件:(e.detail.xxx) window.addEventListener('doit', function(e){ //获取参数值 var imagePath = e.d ...

  10. SharePoint 2010用“localhost”方式访问网站,File not found问题处理方式

    场景:本地服务器上,用“localhost”方式访问网站:在某网站集(Site Collection)下的子网站(Sub Site)中,点击网站权限菜单(Site permissions)等关于调用L ...