博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用synchronized(非this对象)同步代码块解决脏读问题
阅读量:6957 次
发布时间:2019-06-27

本文共 4782 字,大约阅读时间需要 15 分钟。

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

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

你可能感兴趣的文章
从智能电视开始,PPTV与Letv全线开战?
查看>>
ps切图技巧
查看>>
outlook 2007 or 2010 的OLK 4文件夹在WIN 7系统存放在哪儿?
查看>>
centos 单用户登录(无法启动 问题处理)
查看>>
python的时间比较
查看>>
设计数据结构SetOfStacks, 由多个栈组成,并且在前一个栈填满时新建一个栈
查看>>
查看mysql版本和字符编码
查看>>
Win7 & Win XP安装小米驱动
查看>>
主元素
查看>>
ASP.NET夜话笔记10
查看>>
SQL语句修改多条记录某一字段的值
查看>>
CSS注意事项(一)
查看>>
滴滴出行跨出国门,再战Uber胜算有多大?
查看>>
山寨文化的博弈论解读
查看>>
ZCS证书的重新签发
查看>>
Python 之time模块
查看>>
备份 Outlook 2010 中接收到的邮件和联系人
查看>>
用open***组建lan to lan ***
查看>>
我的友情链接
查看>>
Vuejs学习系列(十七)--模板语法(三)
查看>>