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

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. linux性能评估与分析工具

    linux是一个开源系统,其内核负责管理系统的进程,内存,设备驱动程序,文件和网络系统, 决定着系统的性能和稳定性.由于内核源码很容易获取,任何人都可以将自己认为优秀的代码 加入到其中.linux默认 ...

  2. Jackson2.1.4 序列化格式化时间

    public class User { private int id; private Date birthday; private double money; private String name ...

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

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

  4. java-servlet的url-pattern匹配规则详细描述

    http://www.cnblogs.com/51kata/p/5152400.html http://www.cnblogs.com/canger/p/6084846.html 一.概述 在利用se ...

  5. AWS SDK for C++调用第三方S3 API

    这里介绍AWS SDK for C++ 1.0.x版本,比如下载: https://github.com/aws/aws-sdk-cpp/archive/1.0.164.tar.gz 环境:RHEL/ ...

  6. [转]安装openfire后admin无法登录管理控制平台

    安装完openfire登录管理控制提示: Login failed:make sure your username and password are correct and that you’re a ...

  7. selenium测试(Java)(三)

    控制浏览器: http://www.cnblogs.com/moonpool/p/5657752.html

  8. Java 关于finally、static

    论坛上看到的两道题目,如下: //为啥运行结果是1 0 不是 0 0呢 谁能解释下啊 public class FinallyDemo { static int value = 0; static i ...

  9. 【转】C# URL短地址压缩算法及短网址原理解析

    这篇文章主要介绍了C# URL短地址压缩算法及短网址原理解析,本文重点给出了算法代码,需要的朋友可以参考下 短网址应用已经在全国各大微博上开始流行了起来.例如QQ微博的url.cn,新郎的sinaur ...

  10. winform程序_根据输入的sql生成excel(字段名与sql一致)

    自己打开看吧 app.config可配置数据库路径 excel保存路径.... 源码下载链接: http://pan.baidu.com/s/1bnHPhdd