package com.neutron.t06;
import java.util.concurrent.TimeUnit;
/**
* 对业务写方法加锁,对业务对方法不加锁,容易产生脏读现象
*/
public class T06 {
String name;
double balance;
public synchronized void set(String name, double balance) {
this.name = name;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.balance = balance;
}
public /*synchronized*/ double getBalance(String name) {
return balance;
}
/**
* 分析执行思路:
* 1.创建对象执行set方法时,name赋值后睡上2秒,此时balance等于0.0
* 2.主线程睡1秒
* 3.打印boss的账户,此时set方法才睡1秒,并没有执行balance赋值,此时balance等于0.0
* 4.主线程睡2秒,此时set方法睡过了2秒,balance已经赋值为2000
* 5.打印boss的账户,此时balance是2000
*/
public static void run2() {
T06 t06 = new T06();
new Thread(() ->t06.set("boss", 2000)).start();
try {
TimeUnit.SECONDS.sleep(1);
// 作用类似于:Thread.sleep(1);是对Thread.sleep的进一步封装,可读性良好
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t06.getBalance("boss"));
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t06.getBalance("boss"));
}
/*
运行结果:
0.0
2000.0
*/
public static void main(String[] args) {
run2();
}
}
/*
过程解说:
1.在写的过程中锁,但获取方法不锁定,那么在写的过程中,调用了不锁定的读方法
即在set方法中name和balance之间执行get方法,返回的balance值是0
2.解决方案是读写方法都加锁,并且使用的是同一把锁,目前都是this。
get方法中将注释内容synchronized取消即可。
*/
thread06 - 读写加锁
最新推荐文章于 2023-10-17 23:50:37 发布