一、脏读
在多线程中,有时会出现多个线程对同一个对象的变量进行并发访问的情形,如果不做正确的同步处理,那么产生的后果就是“脏读”,也就是获取到的数据其实是被修改过的。
二、多线程线程安全实例
举例:两个线程分别获取不同的userName对应的num值。
ThreadSynch类,不同的userName对应不同的num值,“zhangsan”对应的num值是100,其他的userName对应的num值是200
public class ThreadSynch { private int num; public void getNumByUserName(String userName){ if("zhangsan".equals(userName)){ try { num = 100; System.out.println("zhangsan getNum over"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }else{ num = 200; System.out.println("someBody else getNum over"); } System.out.println(userName + "======" + num); } }
定义两个线程去获取不同的userName对应的num值,线程1获取“zhangsan”对应的num值
public class Thread01 extends Thread{ private ThreadSynch threadSynch; public Thread01(ThreadSynch threadSynch) { this.threadSynch = threadSynch; } @Override public void run() { threadSynch.getNumByUserName("zhangsan"); } }
线程2获取“lisi”对应的num值
public class Thread02 extends Thread{ private ThreadSynch threadSynch; public Thread02(ThreadSynch threadSynch) { this.threadSynch = threadSynch; } @Override public void run() { threadSynch.getNumByUserName("lisi"); } }
测试,通过上面两个线程去获取对应的num值
public class Test { public static void main(String[] args) { ThreadSynch threadSynch = new ThreadSynch(); Thread01 thread01 = new Thread01(threadSynch); Thread02 thread02 = new Thread02(threadSynch); thread01.start(); thread02.start(); } }
按说,结果应该是:“zhangsan”对应的num值是100,“lisi”对应的num值是200,看一下控制台的打印,“zhangsan”和“lisi”的num值都是200
zhangsan getNum over someBody else getNum over lisi======200 zhangsan======200
其实就算是把Thread.sleep(1000)去掉的话,运行多次的话也会捕捉到线程安全的问题
zhangsan getNum over zhangsan======200 someBody else getNum over lisi======200
分析一下上述的线程安全问题是怎么产生的:
1、thread01先运行,去获取“zhangsan”对应的num值,此时num值已经被赋值为100了,然后开始睡眠1秒,控制台显示“zhangsan getNum over”
2、在thread01睡眠的时候,thread02开始运行或是运行结束了,此时num值已经由100改成了200,控制台显示“someBody else getNum over lisi======200”
3、thread01睡眠结束,但由于thread01和thread02操作的是同一个对象的num属性,所以此时num值已经由100变成了200,控制套显示“zhangsan======200”
产生问题的原因找到了,解决就很简单了。thread01操作threadSynch对象的getNumByUserName()方法的时候,在其结束之前不要让thread02进入该方法执行,即给getNumByUserName()方法加一个同步锁。
public class ThreadSynch { private int num; public synchronized void getNumByUserName(String userName){ if("zhangsan".equals(userName)){ num = 100; System.out.println("zhangsan getNum over"); }else{ num = 200; System.out.println("someBody else getNum over"); } System.out.println(userName + "======" + num); } }
结果:
zhangsan getNum over zhangsan======100 someBody else getNum over lisi======200
三、
https://blog.csdn.net/xiao__gui/article/details/8188833#commentBox