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

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. Android——适配器其他组件(AutoCompleteTextView:自动完成文本编辑框;Spinner:下拉列表)

    activity_activitywenben.xml <?xml version="1.0" encoding="utf-8"?> <Lin ...

  2. [爬虫]Python爬虫进阶

    请跳转到以下页面查看: 爬虫进阶

  3. elasticsearch安装与使用(6)-- Logstash安装与配置

    由于elasticsearch的search guard 不支持 elasticsearch的jdbc,所以如果安装了search guard认证插件之后,基本上jdbc就废了,所以我们需要用到log ...

  4. jquery 表格排序,实时搜索表格内容

    jquery 表格排序,实时搜索表格内容   演示 XML/HTML Code <table class="table-sort"> <thead> < ...

  5. GIt的基本知识

    以前已经把git 看过一遍了,由于好久没有用它 ,现在已经忘了.现在呢,要用它进行同步代码,所以呢,我打算记一记,再复习复习. 参考文件:https://git-scm.com/book/zh/v2 ...

  6. gsoap 学习 1-如何使用

    新年伊始,想把onvif和gsoap boa这三个东西学习下,并作下笔记,当然为了省时间,我昨天下午看了一个下午的gsaop官网pdf感触良多,也做了小测试,废话少说,一下也有一些是摘自网友博客,大部 ...

  7. 【Java面试题】18 java中数组有没有length()方法?string没有lenght()方法?下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";

    数组没有length()这个方法,有length的属性.String有有length()这个方法. int a[]; a.length;//返回a的长度 String s; s.length();// ...

  8. maven 打包可执行jar的两种方法

    1.修改pom.xml增加如下内容 <build> <pluginManagement> <plugins> <plugin> <groupId& ...

  9. MVC+LINQToSQL的Repository模式之(二)数据基类

    namespace Data.TEST{    /// <summary>    /// 数据操作基类    /// </summary>    public abstract ...

  10. linux环境,crontab报错Authentication token is no longer valid; new one required You (aimonitor) are not allowed to access to (crontab) because of pam configuration.

    问题描述: 今天同事反应,一个系统上的某些数据没有生成,看了下,怀疑定时任务没有执行,就看下了crontab,发现报了下面的错误: [aimonitor@4A-LF-w08 ~]$ crontab - ...