使用多线程出现脏读,得到的结果不是设计时想要的怎么办呢?

直接看示例:

出现脏读的程序

DealThread.java

public class DealThread implements Runnable {

private String username;

public void setUsername(String username) {

this.username = username;

}

@Override

public void run() {

System.out.println(" in run " + Thread.currentThread().getName() + " " + username);

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(" out run " + Thread.currentThread().getName() + " " + username);

}

}

Run2_2.java

public class Run2_2 {

public static void main(String[] args) {

DealThread d1 = new DealThread();

d1.setUsername("aa");

Thread t1 = new Thread(d1,"A");

t1.start();

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

d1.setUsername("bb");

Thread t2 = new Thread(d1,"B");

t2.start();

}

}

输出结果是:

in run A  aa

in run B  bb

out run A  bb

out run B  bb

加同步锁和使用不同的DealThread对象都能解决这个问题,但是同步锁加得不对还是不能解决问题的,比如修改DealThread.java

修改方法1:(不能解决)

public class DealThread implements Runnable {

private String username;

public void setUsername(String username) {

this.username = username;

}

@Override

public void run() {

synchronized (this) {

System.out.println(" in run " + Thread.currentThread().getName() + " " + username);

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(" out run " + Thread.currentThread().getName() + " " + username);

}

}

}

输出结果为:

in run A  aa

out run A  bb

in run B  bb

out run B  bb

还是没达到效果,这样已经做对一半了,再给 setUsername加上synchronized就可以了

修改方法2:

public class DealThread implements Runnable {

private String username;

public synchronized void setUsername(String username) {

this.username = username;

}

@Override

public void run() {

synchronized (this) {

System.out.println(" in run " + Thread.currentThread().getName() + " " + username);

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(" out run " + Thread.currentThread().getName() + " " + username);

}

}

}

这样输出结果就为:

in run A  aa

out run A  aa

in run B  bb

out run B  bb

另外一种改法就是修改Run2_2.java  为每个线程分配一个DealThread对象,这样就不会出现脏读

修改方法3:

public class Run2_2 {

public static void main(String[] args) {

DealThread d1 = new DealThread();

d1.setUsername("aa");

Thread t1 = new Thread(d1,"A");

t1.start();

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

DealThread d2 = new DealThread();

d2.setUsername("bb");

Thread t2 = new Thread(d2,"B");

t2.start();

}

}

这样的话两个线程会异步打印出各自的内容,互不影响,效率也会快一点,因为不用等上一个线程释放锁。

结合前面两篇关于多线程synchronized还可以这样改(个人觉得这样比较符合实际开发)

修改方法4:

新建merch.java

public class merch {

private String username;

public String getUsername() {

return username;

}

public synchronized void setUsername(String username) {

this.username = username;

}

}

修改DealThread.java

public class DealThread implements Runnable {

private merch merchA;

DealThread (merch merchA) {

this.merchA = merchA;

}

@Override

public void run() {

synchronized (merchA) {

System.out.println(" in run " + Thread.currentThread().getName() + " " + merchA.getUsername());

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(" out run " + Thread.currentThread().getName() + " " + merchA.getUsername());

}

}

}

修改Run2_2.java

public class Run2_2 {

public static void main(String[] args) {

merch merchA = new merch();

merchA.setUsername("aa");

DealThread d1 = new DealThread(merchA);

Thread t1 = new Thread(d1,"A");

t1.start();

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

merchA.setUsername("bb");

Thread t2 = new Thread(d1,"B");

t2.start();

}

}

这样运行结果还是:

in run A  aa

out run A  aa

in run B  bb

out run B  bb

原理还是给 setUsername 和 输出的代码块加锁

个人即兴写的程序和临时想到的解决方法,如果更优的解决方法请留下高见,谢谢。

java中解决脏读_多线程出现脏读以及解决方法(使用synchronized)相关推荐

  1. java中virtual关键字_浅谈virtual、abstract方法和静态方法、静态变量理解

    说点对这几个容易混淆的词的理解: 1.c++中的virtual方法的 virtual关键字主要是防止继承中重复继承父类的同一个方法而设置的标识. 2.virtual与abstract关键字的不同之处在 ...

  2. java socket建立长连接_Java Web项目中使用Socket通信多线程、长连接的方法

    很多时候在javaweb项目中我们需要用到Socket通信来实现功能,在web中使用Socket我们需要建立一个监听程序,在程序启动时,启动socket监听.我们的应用场景是在java项目中,需要外接 ...

  3. Java中为什么有时候通过指定编码集无法解决乱码

    @TOC Java中为什么有时候通过指定编码集无法解决乱码 当我们编程的时候都遇到过出现乱码的情况,这通常是使用了不匹配的编码表导致的,这是我们可以用指定的编码表的方式解决乱码问题如下面 的代码 St ...

  4. Java中常见的CMS GC问题分析与解决(一)

    Java中常见的CMS GC问题分析与解决(一) 目前,互联网上 Java 的 GC 资料要么是主要讲解理论,要么就是针对单一场景的 GC 问题进行了剖析,对整个体系总结的资料少之又少.前车之鉴,后事 ...

  5. java 中的枚举_说说Java中的枚举(一)

    在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的.例如星期一到星期日七个数据元素组成了一周的"数据 ...

  6. java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法

    Java中的线程让步会让线程让出优先级,而休眠则会让线程进入阻塞状态等待被唤醒,这里我们对比线程等待的wait()方法,来详解Java中的线程让步yield()与线程休眠sleep()方法 线程让步: ...

  7. java类名可以是数字吗_在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数、类型或顺序各不相同,传回的值也可以不相同。这种面向对象程序特性称为( )。_学小易找答案...

    [简答题]Java 支持多继承吗 ? [单选题]以下关于继承的叙述正确的是( ). [单选题]在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数.类型或顺序各不相同,传回的值也 ...

  8. 计算机桌面怎么设置在开始菜单,电脑桌面开始菜单不见了应该如何解决?_开始菜单不见了解决办法介绍...

    电脑桌面开始菜单不见了应该如何解决?_开始菜单不见了解决办法介绍 2018-06-22 16:26:29 近期朋友在电脑使用过程中,电脑桌面的开始菜单突然就消失不见了,以为重启之后就会成功显示出来,但 ...

  9. java中char类型转换成int类型的两种方法

    java中char类型转换成int类型的两种方法 方法一: 第一种利用Integer包装类的方法Integer.parseInt Copychar ch = '9'; if (Character.is ...

最新文章

  1. 谷歌程序员少输一个“”,差点让全球Chrome笔记本变砖
  2. 理解 Memory barrier(内存屏障)无锁环形队列
  3. C语言实现最简单的2048小游戏
  4. mongodb update
  5. 一个对象的内存图及运行流程和3个对象的内存图的运行流程
  6. STM32 之十一 LL 库(low-layer drivers)详解 及 移植说明
  7. servlet 配置 使用_配置HTTPS以与Servlet一起使用
  8. python两个中文队列比较_具有两个优先级的优先级队列Python
  9. leetcode python3 简单题14. Longest Common Prefix
  10. 学习iptables
  11. 怀念经理用鼠标线联网的1990年代当时
  12. Java实现部标JTT1078实时音视频传输指令——视频流负载包(RTP)传输
  13. NoSQL--Redis
  14. m4a怎么转换成mp3,m4a转mp3方法
  15. java dao 是什么_dao java是什么
  16. C#上位机开发串口通信编程——倒计时器开发
  17. 计算机应用安全检查通报,Microsoft 安全通报 4092731
  18. 关于vlc播放器的ActiveX控件调用问题
  19. java 创建目录及文件_java中如何在系统目录下创建文件夹和文件
  20. 里约奥运会闭幕,中国获奖牌榜前三甲

热门文章

  1. C++虚继承(四) --- /d1 reportSingleClassLayout插入看类内存布局
  2. 豆瓣9.8分,周志明的《凤凰架构》,高屋建瓴,推荐(送书)
  3. 忘掉Java并发,先听完这个故事...
  4. 【今晚9点】:对话袁荣喜——一名C程序员的打怪之路
  5. 知乎云敲钟、比特币可购买特斯拉、用户隐私收集新规五一生效、 软件疯长等|Decode the Week...
  6. Linux AV1硬件视频解码将支持Intel Tiger Lake
  7. x265发起者陈敏:别人看我是专注,其实我只是感兴趣而已
  8. 深度学习为图片压缩算法赋能:节省55%带宽
  9. ffplay.c学习-2-数据读取线程
  10. 十个问题理解Linux epoll工作原理