package cn.sdut.concurrent.main;
/**
* @author MaJiatao
* @description: 验证线程原子性
* @created: 2019/09/30 12:51
*/
public class AddCount implements Runnable{
static Integer count = 0;
static Object obj = new Object();
public static void main(String[] args) throws InterruptedException {
AddCount addCount = new AddCount();
Thread thread = new Thread(addCount);
thread.setName("A");
Thread thread2 = new Thread(addCount);
thread2.setName("B");
thread.start();
thread2.start();
thread.join();
thread2.join();
System.out.println(count);
}
synchronized void set(Integer v) {
System.out.println("set " + Thread.currentThread().getName() + " " + v);
count = v;
}
synchronized Integer get() {
return count;
}
@Override
public void run() {
if ("A".equals(Thread.currentThread().getName())) {
add1k();
}
if ("B".equals(Thread.currentThread().getName())) {
updateCount();
}
}
void add1k(){
int index = 0;
synchronized (obj) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (index++ < 1000) {
System.out.println("get " + Thread.currentThread().getName() + " " + get());
set(get() + 1);
}
}
}
void updateCount() {
System.out.println("get " + Thread.currentThread().getName() + " " + get());
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
set(get() + 1000);
}
}
这里将添加方法add1k()因为是组合调用,为了保证原子性,所以需要在前面添加互斥锁;
对于给get/set方法需要添加sync的问题,如果没有添加,会出现下面截图的问题:
两个线程同时对count进行操作,如果get/set没有添加,就会出现可能两个线程同时get()后得到的是同一个值,这样在缓存中各自操作写回内存的时候,就会出现异常.比如:线程1和线程2同时get()得到的是188,线程1操作加1后为189;线程2添加1000后为1188;
当写回内存的时候,线程1先写189,线程2回写1188这样线程2的回写会覆盖掉线程1的回写值.对于出现get A 189 ; set A 1189这是由于cpu运行导致[每次set时候都获取数值 set(get() + 1)]