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

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对象本身作为“对象监视器”

转载于:https://www.cnblogs.com/dream-to-pku/p/6308620.html

使用synchronized(非this对象)同步代码块解决脏读问题相关推荐

  1. 同步代码块解决线程安全

    案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 代码: package com.learn;class ThreadDemo01 implements Runnab ...

  2. 记录一次关于synchronized同步代码块的问题

    本人在学习过程中在一些书籍上关于synchroinzed同步代码块的解释总是如下 synchronized(obj){ --}在使用同步代码块时锁住了obj对象其他线程同时无法访问obj对象, 这很容 ...

  3. java中synchronized(同步代码块和同步方法)详解及区别

    问题的由来: 看到这样一个面试题: ? 1 2 3 4 5 6 //下列两个方法有什么区别 public synchronized void method1(){} public void metho ...

  4. Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】

    视频+资料[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] Java基础--学习笔记(零起点打开java世界的大门)--博 ...

  5. java锁方法和锁代码块_java的同步方法和同步代码块,对象锁,类锁区别

    /** * @author admin * @date 2018/1/12 9:48 * 做用在同一个实例对象上讨论 * synchronized同步方法的测试 * 两个线程,一个线程调用synchr ...

  6. cookie里面用到的关键字_晓龙吊打面试官系列:synchronized关键字入门(同步方法与同步代码块)...

    文章目录 一. 线程安全问题 二.synchronized简介 1) 原子性 2) 可见性 3) 有序性 4)可重入 1. 什么是synchronized 2.什么是同步 3.synchronized ...

  7. 同步代码块Synchronized笔记

    什么是同步代码块(Synchronized Block) 同步代码块简单来说就是将一段代码用一把锁给锁起来, 只有获得了这把锁的线程才访问, 并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同 ...

  8. 6※、线程同步、同步锁、同步代码块的使用、同步锁释放的时机、ReentrantLock可重入锁、公平锁与非公平锁的区别、什么是死锁、线程间的通信(生产者和消费者模式)

    线程锁 1.※线程的同步:(要确保对象锁是一致的) 1.未使用同步锁的抢票 2.使用了同步锁的抢票 3.线程-同步代码块的使用 4.同步方法和代码块的区别 5.同步锁释放的时机 练习:多线程生产手机 ...

  9. 从操作系统的PV操作理解JAVA的synchronized同步方法,同步代码块实现,及比较

    也有利于理解操作系统的同步 知识果然是息息相关的 JAVA同样离不开操作系统的原理,不过他体现在虚拟机JVM中 synchronized关键字是同步关键字 首先我们知道在操作系统里 PV两者操作信息量 ...

  10. notify()唤醒线程,不会立即释放锁对象,需要等到当前同步代码块都执行完后才能释放锁对象

    notify()唤醒线程,不会立即释放锁对象,需要等到当前同步代码块都执行完后才能释放锁对象 public class Test3 {public static void main(String[] ...

最新文章

  1. php减少损耗的方法之一 缓存对象
  2. 2021高考成绩查询大连,2021年大连高考各高中成绩及本科升学率数据排名及分析...
  3. UML总结---UML九种图关系说明
  4. java 判断object类型_Java多态的6大特性|乐字节
  5. 千万数据去重_如何在 1 秒内做到大数据精准去重?
  6. 由ViewStateException: The client disconnected想到的
  7. Patternodes 3 for Mac(创建图形矢量模式工具)
  8. 20.合并两个有序链表
  9. 笔记本计算机显示图标,笔记本电脑声音图标不见了?电脑声音图标显示红叉
  10. VS2015安装教程(带图解+下载地址+超详细)
  11. vue3 使用sass/scss
  12. 软件工程专业就业方向
  13. 物料-贴片电容-标签识别
  14. 计算机型号win7,教你win7系统电脑内存条型号怎么看
  15. 记录一次上网正常但是【登录客户端应用网络异常问题】
  16. 区块链技术与应用-BTC
  17. 图片轮播器——javascript
  18. 视觉slam14讲学习(一)之se3上的定位表示:轨迹显示与轨迹误差
  19. 前端的Vue相关的项目经验
  20. 前端:给中国奥运金牌数做可视化

热门文章

  1. 编译Libgdiplus遇到的问题
  2. unity自带的方法
  3. SharePoint 2013 Preview Single Server 评估环境安装与简单试用
  4. php 字符编码转换
  5. mysql关键字了解
  6. acm集训训练赛(二)D题【并查集】
  7. C#基于RabbitMQ实现客户端之间消息通讯实战演练
  8. 【原创】实战padding oracle漏洞
  9. SP2010开发和VS2010专家食谱--第七章节--使用客户端对象模型
  10. 慢日志之一:开启mysql慢查询日志并使用mysqldumpslow命令查看,分析诊断工具之四...